我对Floyd-Warshall,Dijkstra和Bellman-Ford算法之间的区别是否正确?

Gro*_*Man 22 algorithm graph-theory dijkstra bellman-ford floyd-warshall

我一直在研究这三个,我在下面陈述我的推论.有人能告诉我,我是否已经足够准确地理解它们了吗?谢谢.

  1. Dijkstra的算法仅在您拥有单个源并且您想知道从一个节点到另一个节点的最小路径时使用,但在这种情况下失败

  2. 当任何所有节点都可以作为源时,使用Floyd-Warshall的算法,因此您希望最短距离从任何源节点到达任何目标节点.只有在出现负循环时才会失败

(这是最重要的一个.我的意思是,这是我最不确定的:)

3.Bellman-Ford像Dijkstra一样使用,当时只有一个来源.这可以处理负重量,它的工作方式与Floyd-Warshall相同,除了一个来源,对吗?

如果你需要看看,相应的算法是(礼貌的维基百科):

贝尔曼 - 福特:

 procedure BellmanFord(list vertices, list edges, vertex source)
   // This implementation takes in a graph, represented as lists of vertices
   // and edges, and modifies the vertices so that their distance and
   // predecessor attributes store the shortest paths.

   // Step 1: initialize graph
   for each vertex v in vertices:
       if v is source then v.distance := 0
       else v.distance := infinity
       v.predecessor := null

   // Step 2: relax edges repeatedly
   for i from 1 to size(vertices)-1:
       for each edge uv in edges: // uv is the edge from u to v
           u := uv.source
           v := uv.destination
           if u.distance + uv.weight < v.distance:
               v.distance := u.distance + uv.weight
               v.predecessor := u

   // Step 3: check for negative-weight cycles
   for each edge uv in edges:
       u := uv.source
       v := uv.destination
       if u.distance + uv.weight < v.distance:
           error "Graph contains a negative-weight cycle"
Run Code Online (Sandbox Code Playgroud)

Dijkstra算法:

 1  function Dijkstra(Graph, source):
 2      for each vertex v in Graph:                                // Initializations
 3          dist[v] := infinity ;                                  // Unknown distance function from 
 4                                                                 // source to v
 5          previous[v] := undefined ;                             // Previous node in optimal path
 6                                                                 // from source
 7      
 8      dist[source] := 0 ;                                        // Distance from source to source
 9      Q := the set of all nodes in Graph ;                       // All nodes in the graph are
10                                                                 // unoptimized - thus are in Q
11      while Q is not empty:                                      // The main loop
12          u := vertex in Q with smallest distance in dist[] ;    // Start node in first case
13          if dist[u] = infinity:
14              break ;                                            // all remaining vertices are
15                                                                 // inaccessible from source
16          
17          remove u from Q ;
18          for each neighbor v of u:                              // where v has not yet been 
19                                                                                 removed from Q.
20              alt := dist[u] + dist_between(u, v) ;
21              if alt < dist[v]:                                  // Relax (u,v,a)
22                  dist[v] := alt ;
23                  previous[v] := u ;
24                  decrease-key v in Q;                           // Reorder v in the Queue
25      return dist;
Run Code Online (Sandbox Code Playgroud)

弗洛伊德 - 沃肖尔:

 1 /* Assume a function edgeCost(i,j) which returns the cost of the edge from i to j
 2    (infinity if there is none).
 3    Also assume that n is the number of vertices and edgeCost(i,i) = 0
 4 */
 5
 6 int path[][];
 7 /* A 2-dimensional matrix. At each step in the algorithm, path[i][j] is the shortest path
 8    from i to j using intermediate vertices (1..k?1).  Each path[i][j] is initialized to
 9    edgeCost(i,j).
10 */
11
12 procedure FloydWarshall ()
13    for k := 1 to n
14       for i := 1 to n
15          for j := 1 to n
16             path[i][j] = min ( path[i][j], path[i][k]+path[k][j] );
Run Code Online (Sandbox Code Playgroud)

Guy*_*ini 19

你对前两个问题是正确的,关于Floyd-Warshall的目标(找到所有对之间的最短路径),而不是关于Bellman-Ford和Floyd-Warshall之间的关系:两种算法都使用动态编程来找到最短的路径,但FW与从每个起始节点到每个其他节点运行BF不同.

在BF中,问题是:使用最多k步从源到目标的最短路径是什么,运行时间是O(E V).如果我们将它运行到每个其他节点,则运行时间将为O(E V ^ 2).

在FW中,问题是:对于所有节点i,j,k,从i到j到k的最短路径是多少.这导致O(V ^ 3)运行时间 - 对于每个起始节点优于BF(对于密集图,最高为| V |).

关于负周期/权重的另一个注意事项:Dijkstra可能根本无法给出正确的结果.BF和FW不会失败 - 他们将正确地说明没有最小权重路径,因为负权重是无限制的.


aru*_*zhi 8

单源最短路径:

Dijkstra算法 - 不允许负重量 - O(E + Vlg(V))

Bellman福特算法 - 允许负权重.但如果存在负循环,Bellman ford将检测-ve循环 - O(VE)

定向非循环图 - 顾名思义它只适用于DAG - O(V + E)

所有对最短路径:

Dijkstra算法 - 不允许负重 - O(VE + V ^ 2lg(V))

Bellman福特算法 - O(V ^ 2E)

矩阵链乘法 - 复杂度与Bellman ford算法相同

Floyd Warshall算法 - 使用动态编程方法 - 复杂度为O(V ^ 3)