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

时间:2012-07-28 21:03:19

标签: algorithm graph-theory dijkstra floyd-warshall bellman-ford

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

  1. Dijkstra算法仅在您拥有单一来源且您想知道从一个节点到另一个节点的最小路径时使用,但在this

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

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

    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"
    

    的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;
    

    弗洛伊德-沃肖尔:

     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] );
    

2 个答案:

答案 0 :(得分: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不会失败 - 他们会正确地说明没有最小权重路径,因为负权重是无限制的。

答案 1 :(得分:8)

单源最短路径:

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

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

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

所有对最短路径:

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

Bellman ford算法 - O(V ^ 2E)

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

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