加权图的BFS算法 - 求最短距离

时间:2016-07-14 19:29:11

标签: algorithm graph shortest-path breadth-first-search weighted-graph

我在这个主题上看过很多帖子(即post1post2post3)但是这些帖子都没有提供备份相应查询的算法。因此,我不确定接受这些帖子的答案。

在这里,我提出了一个基于BFS的最短路径(单源)算法,适用于非负加权图。任何人都可以帮助我理解为什么BFS(根据以下基于BFS的算法)不用于此类问题(涉及加权图)!

算法:

SingleSourceShortestPath (G, w, s):
    //G is graph, w is weight function, s is source vertex
    //assume each vertex has 'col' (color), 'd' (distance), and 'p' (predecessor) 
        properties

    Initialize all vertext's color to WHITE, distance to INFINITY (or a large number
        larger than any edge's weight, and predecessor to NIL
    Q:= initialize an empty queue

    s.d=0
    s.col=GREY     //invariant, only GREY vertex goes inside the Q
    Q.enqueue(s)  //enqueue 's' to Q

    while Q is not empty
        u = Q.dequeue()   //dequeue in FIFO manner
        for each vertex v in adj[u]  //adj[u] provides adjacency list of u
             if v is WHITE or GREY       //candidate for distance update
                  if u.d + w(u,v) < v.d        //w(u,v) gives weight of the 
                                               //edge from u to v
                      v.d=u.d + w(u,v)
                      v.p=u
                      if v is WHITE
                          v.col=GREY    //invariant, only GREY in Q
                          Q.enqueue(v)
                      end-if
                  end-if
              end-if
         end-for
         u.col=BLACK  //invariant, don't update any field of BLACK vertex.
                      // i.e. 'd' field is sealed 
    end-while

运行时:据我所知,它是O(| V | + | E |),包括初始化成本

如果此算法类似于任何现有算法,请告诉我

4 个答案:

答案 0 :(得分:3)

由于伪代码是Dijksta的算法,其FIFO队列而不是优先级队列,总是根据距离进行排序。到目前为止,每个访问过的(黑色)顶点计算出的最短距离的关键不变量不一定正确。这就是为什么优先级队列是(正)加权图中距离计算必须的原因。

您可以将算法用于未加权的图表,或者通过将权重n替换为权重为1的边缘连接的n-1顶点来使每个边缘不加权。

反例:

首先Q.enqueue(s)之后的计算状态:

State of the computation after first <code>Q.enqueue(s)</code>

第一次迭代后的计算状态:

State of the computation after first iteration

此图表是一个反例,重要的是adj[u] = adj[S] = [F, M]而不是[M, F],因此F首先排在Q.enqueue(v)

之前

第二次迭代后的计算状态:

State of the computation after second iteration

由于顶点F首先由u = Q.dequeue()出列(与使用距离优先级队列时不同),此迭代不会更新任何距离,F将变为黑色且不变量将为侵犯。

最后一次迭代后的计算状态:

Final state

答案 1 :(得分:0)

看起来你实现了Dijkstra的经典算法,没有堆。您将遍历每个边缘的矩阵,然后查看是否可以改善距离。

答案 2 :(得分:0)

我以前也有同样的困惑。查看SPFA算法。当作者于1994年发布此算法时,他声称它的算法比Dijkstra的O(E)复杂度更好,这是错误的。

您可以将此算法视为Bellman-Ford的变体/改进。最糟糕的情况仍然是O(VE),因为一个节点可能会多次从队列中添加/删除。但是对于随机稀疏图,由于它跳过了许多不必要的放松步骤,因此它的性能肯定优于原始的Bellman-Ford。

尽管“ SPFA”这个名称在学术界似乎并不为人所接受,但由于其简单易用,在ACM学生中广受欢迎。性能上最好是Dijkstra。

答案 3 :(得分:0)

通常人们说没有边缘重量时是BFS。

  • BFS :具有恒定边缘权重的图形。

  • Dijkstra :带有边缘权重的图形(如果
    可以处理一些负边缘 它没有负周期)

  • 贝尔曼福德和SPFA :负周期图。

您的代码是Dijkastra或SPFA的变体,而不是简单的BFS(尽管它是 IS 基于基于BFS的算法)