精华内容
下载资源
问答
  • SPFA最短路径算法图解

    2017-03-23 21:24:32
     适用范围:给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法...算法思想:我们用数组d记录每个结点的最短路径估计值,用邻接表来存储图G。我们采取的方
    

    适用范围:给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了。 我们约定有向加权图G不存在负权回路,即最短路径一定存在。当然,我们可以在执行该算法前做一次拓扑排序,以判断是否存在负权回路,但这不是我们讨论的重点。

    算法思想:我们用数组d记录每个结点的最短路径估计值,用邻接表来存储图G。我们采取的方法是动态逼近法:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止

     

    期望的时间复杂度O(ke), 其中k为所有顶点进队的平均次数,可以证明k一般小于等于2。

     

    实现方法:

      建立一个队列,初始时队列里只有起始点,再建立一个表格记录起始点到所有点的最短路径(该表格的初始值要赋为极大值,该点到他本身的路径赋为0)。然后执行松弛操作,用队列里有的点作为起始点去刷新到所有点的最短路,如果刷新成功且被刷新点不在队列中则把该点加入到队列最后。重复执行直到队列为空。

    判断有无负环:
      如果某个点进入队列的次数超过N次则存在负环(SPFA无法处理带负环的图)

     


     

     

     

    首先建立起始点a到其余各点的
    最短路径表格

                                     

    首先源点a入队,当队列非空时:
     1、队首元素(a)出队,对以a为起始点的所有边的终点依次进行松弛操作(此处有b,c,d三个点),此时路径表格状态为:

                                     

    在松弛时三个点的最短路径估值变小了,而这些点队列中都没有出现,这些点
    需要入队,此时,队列中新入队了三个结点b,c,d

    队首元素b点出队,对以b为起始点的所有边的终点依次进行松弛操作(此处只有e点),此时路径表格状态为:

                                    

    在最短路径表中,e的最短路径估值也变小了,e在队列中不存在,因此e也要
    入队,此时队列中的元素为c,d,e

    队首元素c点出队,对以c为起始点的所有边的终点依次进行松弛操作(此处有e,f两个点),此时路径表格状态为:

                                    

    在最短路径表中,e,f的最短路径估值变小了,e在队列中存在,f不存在。因此
    e不用入队了,f要入队,此时队列中的元素为d,e,f

     队首元素d点出队,对以d为起始点的所有边的终点依次进行松弛操作(此处只有g这个点),此时路径表格状态为:

     

     

                                  

    在最短路径表中,g的最短路径估值没有变小(松弛不成功),没有新结点入队,队列中元素为f,g

    队首元素f点出队,对以f为起始点的所有边的终点依次进行松弛操作(此处有d,e,g三个点),此时路径表格状态为:


                                   

    在最短路径表中,e,g的最短路径估值又变小,队列中无e点,e入队,队列中存在g这个点,g不用入队,此时队列中元素为g,e

    队首元素g点出队,对以g为起始点的所有边的终点依次进行松弛操作(此处只有b点),此时路径表格状态为:

                              

    在最短路径表中,b的最短路径估值又变小,队列中无b点,b入队,此时队列中元素为e,b
    队首元素e点出队,对以e为起始点的所有边的终点依次进行松弛操作(此处只有g这个点),此时路径表格状态为:

     

                             

    在最短路径表中,g的最短路径估值没变化(松弛不成功),此时队列中元素为b

    队首元素b点出队,对以b为起始点的所有边的终点依次进行松弛操作(此处只有e这个点),此时路径表格状态为:

                            

    在最短路径表中,e的最短路径估值没变化(松弛不成功),此时队列为空了

    最终a到g的最短路径为14


    原文出处:http://www.360doc.com/content/13/1208/22/14357424_335569176.shtml

    展开全文
  • 这篇文章以最短路径问题为例来展开讨论两种搜索方法的思路。 可求最短路径的结构往往是有向带权图,用代码表示就是 public class Graph { // 有向有权图的邻接表表示 private LinkedList<Edge> adj[]; // ...

    单源最短路径典型的启发式搜索有两种,分别是贪婪最佳优先搜索(Greedy best-first search)和A*寻路搜索。这篇文章以最短路径问题为例来展开讨论两种搜索方法的思路。

    First Step:确定路径的存储结构

    可求最短路径的结构往往是有向带权图,用代码表示就是

    public class Graph { // 有向有权图的邻接表表示
      private LinkedList<Edge> adj[]; // 邻接表
      private int v; // 顶点个数
      public Graph(int v) {
        this.v = v;
        this.adj = new LinkedList[v];
        for (int i = 0; i < v; ++i) {
          this.adj[i] = new LinkedList<>();
        }
      }
      public void addEdge(int s, int t, int w) { // 添加一条边
        this.adj[s].add(new Edge(s, t, w));
      }
      private class Edge {
        public int sid; // 边的起始顶点编号
        public int tid; // 边的终止顶点编号
        public int w; // 权重
        public Edge(int sid, int tid, int w) {
          this.sid = sid;  this.tid = tid;  this.w = w;
        }
      }
      //这个类是为了dijkstra实现用的
      private class Vertex {
        public int id; // 顶点编号ID
        public int dist; // 从起始顶点到这个顶点的距离
        public Vertex(int id, int dist) {
          this.id = id;
          this.dist = dist;
        }
      }
    }
    

    Second Step:不同寻路算法实现

    1.贪婪最佳优先搜索——Dijkstra算法

      用贪心思路,每一步都选最优。不足之处有:(1)没办法保证全局最优,甚至可能选入死循环路径。(2)时间复杂度和空间复杂度最坏情况都可达到O(b^m),b是所有结点总数,m是搜索空间的最大深度
    

    Dijkstra算法是贪心/BFS的升级版。当一个图中的每条边都加上权值后,BFS就没办法求一个点到另一个点的最短路径了。这时候,需要用到Dijkstra算法。从最基本原理上讲,把BFS改成Dijkstra算法,只需要把“队列”改成“优先队列”就可以了。
    四个核心参数:
    vertexs[i]:V0到Vi的最短路径长度(或权重)。
    predecessor[i]:存当前最短路径上的倒数第二个结点。
    PriorityQueue :每一位存Vi以及vertexs[i],会自动根据vertex[i]的值排序,小顶堆。
    inqueue[i]:bool变量,Vi计入最短路径则为1,不计入为0;
    在这里插入图片描述
    图片来源:BFS算法讲解

    // 因为Java提供的优先级队列,没有暴露更新数据的接口,所以我们需要重新实现一个
    private class PriorityQueue { // 根据vertex.dist构建小顶堆
      private Vertex[] nodes;
      private int count;
      public PriorityQueue(int v) {
        this.nodes = new Vertex[v+1];
        this.count = v;
      }
    }
    public void dijkstra(int s, int t) { // 从顶点s到顶点t的最短路径
      int[] predecessor = new int[this.v]; // 用来还原最短路径
      Vertex[] vertexes = new Vertex[this.v];
      for (int i = 0; i < this.v; ++i) {
        vertexes[i] = new Vertex(i, Integer.MAX_VALUE);
      }
      PriorityQueue queue = new PriorityQueue(this.v);// 小顶堆
      boolean[] inqueue = new boolean[this.v]; // 标记是否进入过队列
      vertexes[s].dist = 0;
      queue.add(vertexes[s]);
      inqueue[s] = true;
      while (!queue.isEmpty()) {
        Vertex minVertex= queue.poll(); // 取堆顶元素并删除
        if (minVertex.id == t) break; // 最短路径产生了
        for (int i = 0; i < adj[minVertex.id].size(); ++i) {
          Edge e = adj[minVertex.id].get(i); // 取出一条minVetex相连的边
          Vertex nextVertex = vertexes[e.tid]; // minVertex-->nextVertex
          if (minVertex.dist + e.w < nextVertex.dist) { // 更新next的dist
            nextVertex.dist = minVertex.dist + e.w;
            predecessor[nextVertex.id] = minVertex.id;
            if (inqueue[nextVertex.id] == true) {
              queue.update(nextVertex); // 更新队列中的dist值
            } else {
              queue.add(nextVertex);
              inqueue[nextVertex.id] = true;
            }
          }
        }
      }
      // 输出最短路径
      System.out.print(s);
      print(s, t, predecessor);
    }
    private void print(int s, int t, int[] predecessor) {
      if (s == t) return;
      print(s, predecessor[t], predecessor);
      System.out.print("->" + t);
    }
    

    2.A*算法

    Dijkstra算法是用一个优先队列来记录遍历的顶点与相应路径长度,如果顶点到起点的路径约短,就越先从队列中取出来做扩展,虽然最后在整个图里找到最有路径,但是开头难免曲折。(最优路径可能开始的边权重很大)
    快速寻路的A算法应运而生,不足是它只能找到次优解,不能保证最优。
    A
    算法评估函数公式f(i) = g(i) + h(i) ; 而Dijkstra算法是f(i) = g(i) ;
    其中g(i)是从起始到当前结点n的最小代价值 ,h(i)是从当前到目标结点路径的最小代价值,f(i)是经过结点i,具有最小代价值的路径。
    其中h(i)一般可以通过
    A* 算法的代码实现的主要逻辑是下面这段代码。它跟 Dijkstra 算法的代码实现,主要有 3 点区别:
    优先级队列构建的方式不同。A* 算法是根据 f 值(也就是刚刚讲到的 f(i)=g(i)+h(i))来构建优先级队列,而 Dijkstra 算法是根据 dist 值(也就是刚刚讲到的 g(i))来构建优先级队列;

    public void astar(int s, int t) { // 从顶点s到顶点t的路径
      int[] predecessor = new int[this.v]; // 用来还原路径
      // 按照vertex的f值构建的小顶堆,而不是按照dist
      PriorityQueue queue = new PriorityQueue(this.v);
      boolean[] inqueue = new boolean[this.v]; // 标记是否进入过队列
      vertexes[s].dist = 0;
      vertexes[s].f = 0;
      queue.add(vertexes[s]);
      inqueue[s] = true;
      while (!queue.isEmpty()) {
        Vertex minVertex = queue.poll(); // 取堆顶元素并删除
        for (int i = 0; i < adj[minVertex.id].size(); ++i) {
          Edge e = adj[minVertex.id].get(i); // 取出一条minVetex相连的边
          Vertex nextVertex = vertexes[e.tid]; // minVertex-->nextVertex
          if (minVertex.dist + e.w < nextVertex.dist) { // 更新next的dist,f
            nextVertex.dist = minVertex.dist + e.w;
            nextVertex.f 
               = nextVertex.dist+hManhattan(nextVertex, vertexes[t]);
            predecessor[nextVertex.id] = minVertex.id;
            if (inqueue[nextVertex.id] == true) {
              queue.update(nextVertex);
            } else {
              queue.add(nextVertex);
              inqueue[nextVertex.id] = true;
            }
          }
          if (nextVertex.id == t) { // 只要到达t就可以结束while了
            queue.clear(); // 清空queue,才能推出while循环
            break; 
          }
        }
      }
      // 输出路径
      System.out.print(s);
      print(s, t, predecessor); // print函数请参看Dijkstra算法的实现
    }
    

    A* 算法在更新顶点 dist 值的时候,会同步更新 f 值;
    循环结束的条件也不一样。Dijkstra 算法是在终点出队列的时候才结束,A* 算法是一旦遍历到终点就结束。
    A* 算法之所以不能像 Dijkstra 算法那样,找到最短路径,主要原因是两者的 while 循环结束条件不一样。刚刚我们讲过,Dijkstra 算法是在终点出队列的时候才结束,A* 算法是一旦遍历到终点就结束。对于 Dijkstra 算法来说,当终点出队列的时候,终点的 dist 值是优先级队列中所有顶点的最小值,即便再运行下去,终点的 dist 值也不会再被更新了。对于 A* 算法来说,一旦遍历到终点,我们就结束 while 循环,这个时候,终点的 dist 值未必是最小值。

    展开全文
  • 而最小费用流的最短路径算法,则是从0流开始,往最短路径上分配流量,直到流量达到v0为止。 最小费用流的最短路径算法图例 容量-费用网络,初始分配0流: 找出残余容量网络上的最短路径:s->2->t(距离为4)...

    屈婉玲《算法设计与分析》第2版第7章网络流算法学习笔记。

    概述

    最小费用流的负回路算法,是先任意分配流量v0,再将流量调整到权值较小的边上,参考:

    基于Floyd算法的最小费用流的负回路算法(图解)

    而最小费用流的最短路径算法,则是从0流开始,往最短路径上分配流量,直到流量达到v0为止。

    最小费用流的最短路径算法图例

    容量-费用网络,初始分配0流:
    在这里插入图片描述
    找出残余容量网络上的最短路径:s->2->t(距离为4),分配5个单位流量,得到f1:
    在这里插入图片描述
    更新残余网络找出最短路径:s->1->2->t (距离为5),分配1个单位流量,得到f2:
    在这里插入图片描述
    更新残余网络找出最短路径:s->1->t (距离为6),分配2个单位流量(v0-f2=2),得到f3:
    在这里插入图片描述
    至此流量达到v0,f3即为所求。

    伪代码

    1. f ← 0
    2. 构造N(f)
    3. 调用Floyd算法计算N(f)中s-t最短路径
    4. if N(f)无s-t路径 then return “无流量v0的可行流”  //f是最大流,且v(f)<v0
    5.N(f)的s-t增广路径中找出最短路径
    6. 为最短路径尽可能分配流量,且不超过v0,f ← f1
    7. if v(f)<v0 then goto 2 
    8. return f
    

    Ford算法

    上面算法中找最短路径时,使用L.R.Ford 提出的 Ford 算法替代Floyd算法更好,因为只需求单源最短路径。Ford算法可以求无负回路的赋权有向图中单源最短路径(和Dijkstra条件和功能一样)。

    设赋权有向图D=<V, E, w> 无负回路,n=|V|。

    使用动态规划法,记d(k)(i)为D中v1到vi边数不超过k的最短路径的权(2<=i<=n, k>=1),可得递推公式:

    d(0)(1) = 0;  d(0)(i) = +∞, 2<=i<=n
    d(k)(i) = min{d(k-1)(i), d(k-1)(j) + w(j, i)} | <vj, vi>∈E }, 1<=i<=n, k>=1
    

    因为图中无负回路,所以最短路径包含边数<=n-1,所以d(n-1)(i)即为所求。

    为了保存详细路径信息,用h(k)(i)保存i的下一跳,递推公式为:

    h(0)(1) = 1; h(0)(i) = 0, 2<=i<=n
    h(k)(i) = h(k-1)(i), 若d(k-1)(i) <= d(k-1)(j) + w(j, i)
    	      min{j},         若d(k-1)(i) > d(k-1)(j) + w(j, i)
    

    Ford单源最短路径算法图例

    在这里插入图片描述
    由d(4)和h(4)可知:

    v1到v2最短路径长为1, 1->2
    v1到v3最短路径长为1, 1->2->5->3
    v1到v4最短路径长为1, 1->4
    v1到v5最短路径长为1, 1->2->5  
    

    伪代码

    //初始化,k=0
    d(1)1=0h(1)1
    for i←2 to n do
    	d(i)+, h(i)0
    for k←1 to n-1 do
    	for i←1 to n do
    		for <vj, vi>∈E do
    			if d(j)+w(j,i) < d(i) then
    				d(i)d(k-1)(j)+w(j,i)
    				h(i) ← j
    //若n-1次循环后还能更新d(i),说明到该点的最短路径还未找到,那么必定是存在负回路,返回FALSE
    for i←1 to n do
    	for <vj, vi>∈E do
    		if d(j)+w(j,i) < d(i) then
    			return false
    return d, h
    

    算法对比

    对比Floyd算法

    Ford算法复杂度和Floyd算法一样为O(n^3),但Ford算法只保留单源最短路径,Floyd计算并保存多源最短路径,所以比Floyd算法节省空间,效率也较高。

    在找s-t最短路径时Ford算法比Floyd算法更适合。

    对比Dijkstra算法

    Ford算法复杂度也可表示为O(n * m),m = |E|;相比之下,Dijkstra算法复杂度为O(n^2);当图是稀疏图时,二者相差不大。

    Dijkstra算法不能处理有负回路的图,而Ford算法能

    展开全文
  • 内容会持续更新,有错误的地方欢迎...以 S 为源节点,实现Bellman-Ford(中文名:贝尔曼福特算法) 单源最短路径算法。 Dijkstra算法 请见下方图解: 但Dijkstra算法不适用于有负权边的图,所以这里,用Be...

    内容会持续更新,有错误的地方欢迎指正,谢谢!

    前言:博主最近正在学习《算法》这门专业课程,这是该课程的第四次上机题目,我把自己的解题方法分享给大家,欢迎讨论!

    单源最短路径 题目

    以 S 为源节点,实现Bellman-Ford(中文名:贝尔曼福特算法) 单源最短路径算法。

    这里写图片描述

    Dijkstra算法

    请见下方图解:
    这里写图片描述
    但Dijkstra算法不适用于有负权边的图,所以这里,用Bellman-Ford 算法。

    Bellman-Ford 算法

    分析和实现请参考如下两个链接:

    【1】单源最短路径(2):Bellman-Ford 算法
    https://61mon.com/index.php/archives/195/
    【2】单源最短路径(4):总结
    https://61mon.com/index.php/archives/200/

    多源(全成对)最短路径 题目

    这里写图片描述

    实现Floyd_Warshall(中文名:佛洛依德算法) 全成对最短路径算法

    求最短路的Floyd算法框架:

    声明一个二维数组(官方叫:邻接矩阵),用于将有向图转化为这个二维数组matrix,如何转化?
    1. 先将对角线上的元素置0,非对角线上元素置无穷大;
    2. 再将图中互相相连的两点的距离写入到二维数组中;比如下图点1到点2的距离为3,则matrix[0][1] = 3;
    3. Floyd登场:见下方 Floyd分析 板块

    Floyd分析:

    整个算法虽然感觉很麻烦,但其实代码实现却非常简单,核心代码只有五行:

    for(k=1;k<=n;k++)   
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)   
                 if(e[i][j]>e[i][k]+e[k][j])//k为中转点,e[i][k]表示从i到k的路径长度
                     e[i][j]=e[i][k]+e[k][j]; 

    这五行代码的基本思想:传递思想,或叫中转思想。最开始k=1,只允许经过1号顶点(必须经过1号顶点)进行中转;接下来k=2,允许经过1和2号顶点(必须经过2号顶点)进行中转……最后k=n,允许经过1~n号所有顶点(必须经过n号顶点)进行中转,便可求得任意两点之间的最短路程,至于经不经过除k号顶点以外的顶点,要根据实际输入和每条路径的最短长度的计算结果而定。

    用一句话概括就是:求 从i号顶点到j号顶点只经过“前k号点”的最短路程。

    其实这是一种动态规划的思想——1.最优化问题;2.把大问题转化为一系列互相有关系的子问题,子问题的求解依赖于其它子问题的解。动态规划总结:就是根据每步计算的结果一步步地构造出了最优解决方案。

    所以,就有递推式:
    这里写图片描述

    基于迭代的代码:

    #include <iostream>
    using namespace std;
    
    int matrix[6][6];
    
    void Floyd_Warshall(int n) 
    {
        for (int k = 1; k <= n; ++k)
        {
            for (int j = 1; j <= n; ++j) 
            {
                for (int i = 1; i <= n; ++i) 
                {
                    if(matrix[j][i] > matrix[j][k] + matrix[k][i])
                        matrix[j][i] = matrix[j][k] + matrix[k][i]);
                }
            }
        }
    }
    int main() 
    {
        for (int i = 1; i <= 5; i++)//初始化matrix的元素全部为无穷大(一个点到另外一个点)或0(自己到自己)
            for (int j = 1; j <= 5; j++)
                matrix[i][j] = (i != j) ? 100 : 0;  // 初始化 matrix 数组
    
        matrix[1][2] = 3;
        matrix[1][3] = 8;
        matrix[1][5] = -4;
        matrix[2][4] = 1;
        matrix[2][5] = 7;
        matrix[3][2] = 4;
        matrix[4][1] = 2;
        matrix[4][3] = -5;
        matrix[5][4] = 6;
    
        Floyd_Warshall(5);
    
        for (int i = 1; i <= 5; ++i)
        {
            for (int j = 1; j <= 5; ++j)
            {
                cout << matrix[i][j] << "       ";
                if (j == 5)
                    cout << endl<< endl;
            }
        }
        getchar();
        return 0;
    }
    展开全文
  • 最短路径算法,在加权图中找出两点之间的最短路径,有图解描述的很详细
  • 2、最短路径算法

    2020-06-20 21:41:22
    最短路径算法1、Dijkstra算法2、Floyd算法3、Bellman-Ford算法 1、Dijkstra算法 思想:广度优先算法、贪心算法 时间复杂度:是O(n2)O(n^2)O(n2) 算法思想 算法图解 2、Floyd算法 动态规划的思想 时间复杂度为:O...
  • Dijkstra算法用来计算从一个点到其他所有点的最短路径的算法,是一种单源最短路径算法。也就是说,只能计算起点只有一个的情况。 Dijkstra的时间复杂度是O (N2),它不能处理存在负边权的情况。 【算法描述】...
  • 参考Dijkstra算法图解 时间复杂度:O(n^2) 实现查找单源点最短路径问题 贪心算法 步骤 1、和Floyd算法一样,首先对图map进行初始化(各源点间的距离无限大),其次输入源点关系。 2、 两个集合(vis[] 和dis[] ),...
  • 最短路径算法之SPFA算法。

    千次阅读 2013-08-02 22:25:42
    关于求最短路径之一的SPAF算法的总结。 简单的介绍了松弛,求最短路径算法。 重点说明了SPAF算法的过程。 里面有强大的图解,有详尽的说明,加之对此算法的理解。
  • Floyd算法建立在对图的邻接矩阵的操作上,理解Floyd首先要理解邻接矩阵 对于有向图,邻接矩阵的一行代表该顶点的出边,一列代表该顶点的入边 对于无向图则不区分出边与入边,邻接矩阵表示成一个对称矩阵 graph...
  • 思想:Dijkstra是求单源最短路径,Floyd算法是用于求多源最短路径,算出来的是所有的节点到其余各节点之间的最短距离。 Dijkstra算法 先遍历一下还没有在最短路中的点,选出一个距离 已经在最短路集合中的点 ...
  • t 转载于:https://www.cnblogs.com/cc1997/p/10470185.html
  • O(n3) 转载于:https://www.cnblogs.com/cc1997/p/10453549.html
  • 最短路径算法一之Dijkstra算法算法描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。 使用条件:单源最短路径,适用于边权非负的情况Dijkstra算法求最短路径具体...
  • 以通俗易懂的方式(讨论+图解+代码)的形式叙述有向图最经典的最短路径算法:Dijkstra算法和Bellman-Ford算法(另外有SPFA算法)
  • 具体参考《算法图解》这本书第7章讲的,原书是用python写的,我用PHP再写一次,并稍加完善把书上这三道练习题,拿来测试网上再找了一个稍“难”点的题上代码:class ShortPath{protected $graph=[];//只需要存每个...
  • a 转载于:https://www.cnblogs.com/cc1997/p/10470189.html
  • 最短路径算法-----Dijkstra迪杰斯特拉算法

    千次阅读 多人点赞 2020-11-06 16:41:16
    最近巩固一下算法,提高自己内力,网上看到查看到这...迪杰斯特拉算法图解3.迪杰斯特拉算法的代码说明4.迪杰斯特拉算法的源码 转载请注明出处:http://www.cnblogs.com/skywang12345/ 更多内容:数据结构与算法系...
  • 具体参考《算法图解》这本书第7章讲的,原书是用python写的,我用PHP再写一次,并稍加完善 把书上这三道练习题,拿来测试 网上再找了一个稍“难”点的题 上代码: class ShortPath{ protected $graph...
  • 进入图之后,最短路径可谓就是一大重点,最短路径的求法有很多种,每种算法各有各的好处,你会几种呢?下面来逐个讲解。 1 floyed算法  1)明确思想及功效:在图中求最短路还是要分开说的,分别是单源最短路和...
  • 迪杰斯特拉(Dijkstra)算法的描述、图解以及代码实现

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 241
精华内容 96
关键字:

最短路径算法图解