使用BFS加权图

时间:2015-05-23 06:08:44

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

我正在修改单源最短路径算法,在视频中,老师提到 BFS / DFS 无法直接用于查找最短路径一个加权图(我想每个人都已经知道了)并且说要自己解决这个问题。

我想知道为什么它不能用于加权图的确切原因/解释。是由于边缘的重量还是其他因素?有人可以解释我,因为我感到有点困惑。

PS:我经历了this问题和this问题。

3 个答案:

答案 0 :(得分:31)

考虑这样的图表:

A---(3)-----B
|           |
\-(1)-C--(1)/

从A到B的最短路径是通过C(总重量为2)。正常的BFS将直接从A路径到B路径,将B标记为可见,将A标记为C,标记为C。

在下一阶段,从C传播,B已标记为已看到,因此从C到B的路径不会被视为潜在的较短路径,而BFS将告诉您从A到B的最短路径体重为3。

您可以使用Dijkstra's algorithm代替BFS来查找加权图上的最短路径。在功能上,该算法与BFS非常相似,并且可以以与BFS类似的方式编写。唯一改变的是您考虑节点的顺序。

例如,在上图中,从A开始,BFS将处理A - > B,然后A - >; C,然后停在那里,因为已经看到了所有节点。

另一方面,Dijkstra的算法将按如下方式运作:

  1. 考虑A - > C(因为这是来自A的最低边缘重量)
  2. 考虑C - > B(因为这是我们到目前为止已达到的任何节点的最低权重边缘,我们还没有考虑过)
  3. 考虑并忽略A - > B因为已经看过B了。
  4. 请注意,差异仅在于检查边缘的顺序。在转移到其他节点之前,BFS将考虑来自单个节点的所有边缘,而Dijkstra的算法将始终考虑最低权重看不见的边缘,从连接到到目前为止看到的所有节点的边缘集合 。这听起来令人困惑,但伪代码非常简单:

    create a heap or priority queue
    place the starting node in the heap
    dist[2...n] = {∞}
    dist[1] = 0
    while the heap contains items:
       vertex v = top of heap
       pop top of heap
       for each vertex u connected to v:
           if dist[u] > dist[v] + weight of v-->u:
               dist[u] = dist[v] + weight of edge v-->u
               place u on the heap with weight dist[u]
    

    来自维基百科的这个GIF可以很好地显示发生的情况:

    Dijkstra

    请注意,这看起来与BFS代码非常相似,唯一真正的区别是使用堆,按距离节点排序,而不是常规队列数据结构

答案 1 :(得分:3)

虽然这是事实,但您可以在加权图表中使用BFS/DFS,但图表中稍有变化,如果图表的权重为正整数,则可以使用{替换权重为n的边缘{1}}边缘,权重为1,中间节点为n。像这样:

n-1

将是:

A-(4)-B

并且不要在最终的BFS / DFS结果中考虑这些中间节点(如M1,M2,M3)。

这个算法的复杂度是O(V * M),M是我们边缘的最大权重,如果我们知道在我们的特定图A-(1)-M1-(1)-M2-(1)-M3-(1)-B 中这个算法可以考虑,但一般来说这个算法可能没有这么好的表现。

答案 2 :(得分:0)

<块引用>

老师提到BFS/DFS不能直接用于在加权图中寻找最短路径

对于初学者来说,DFS 不在考虑之列,并且根本不适用于最短路径。

其次,this answer 正确解释了为什么 BFS 在带循环的加权图上失败,并建议 Dijkstra's,用优先级队列替换队列,如果找到到达节点的新的、更短的路径,则允许放宽。

然而,并没有提到在加权有向无环图(加权DAG)上,Dijkstra's 是矫枉过正,可以在 O(|V|+|E|) 时间内通过放松每个顶点的拓扑顺序。这种方法也适用于具有负权重边缘的 DAG。

这是高级算法:

distances = {V: infinity for V in vertices}
predecessors = {V: None for V in vertices}

for U in topological_sort(vertices):
    for V in adjacencies(U):
        if distances[V] > distances[U] + edge_weight(U, V): # relax the edge
            distances[V] = distances[U] + edge_weight(U, V)
            predecessors[V] = U

来源: