Algorithm 用BFS求加权图

Algorithm 用BFS求加权图,algorithm,graph,shortest-path,breadth-first-search,Algorithm,Graph,Shortest Path,Breadth First Search,我正在修改单源最短路径算法,在视频中,老师提到,BFS/DFS不能直接用于在加权图中查找最短路径(我想大家都知道了),并说要自己找出原因 我想知道它不能用于加权图的确切原因/解释。是因为边缘的重量还是其他原因?我有点困惑,有人能解释一下吗 PS:我问了一个又一个问题 考虑这样一个图: A---(3)-----B | | \-(1)-C--(1)/ A-(4)-B 从A到B的最短路径是通过C(总重量为2)。正常BFS将直接从A到B,如图所示标记B,以及从A到C,如图所示标记

我正在修改单源最短路径算法,在视频中,老师提到,BFS/DFS不能直接用于在加权图中查找最短路径(我想大家都知道了),并说要自己找出原因

我想知道它不能用于加权图的确切原因/解释。是因为边缘的重量还是其他原因?我有点困惑,有人能解释一下吗


PS:我问了一个又一个问题

考虑这样一个图:

A---(3)-----B
|           |
\-(1)-C--(1)/
A-(4)-B
从A到B的最短路径是通过C(总重量为2)。正常BFS将直接从A到B,如图所示标记B,以及从A到C,如图所示标记C

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

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

例如,在上图中,从A开始,BFS将处理A-->B,然后处理A-->C,并在此处停止,因为已看到所有节点

另一方面,Dijkstra算法的操作如下:

  • 考虑-->C(因为这是A的最低边权重)
  • 考虑C-->B(因为这是我们到目前为止到达的任何节点的最小权重边,我们尚未考虑)
  • 考虑并忽略-->B,因为已经看到了B
  • 请注意,区别仅在于检查边缘的顺序。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提供了一个很好的可视化效果:


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

    虽然这是正确的,但您可以在加权图中使用
    BFS/DFS
    ,只需在图中稍作更改,如果图形的权重为正整数,则可以将边替换为权重
    n
    ,将边替换为权重为1的
    n
    中间节点。大概是这样的:

    A---(3)-----B
    |           |
    \-(1)-C--(1)/
    
    A-(4)-B
    
    将是:

    A-(1)-M1-(1)-M2-(1)-M3-(1)-B
    
    不要在最后的BFS/DFS结果中考虑这些中间节点(如M1、M2、M3)。


    这个算法的复杂度是O(V*M),M是边的最大权重,如果我们知道在特定的图中
    M
    老师提到BFS/DFS不能直接用于在加权图中查找最短路径

    首先,DFS已经不在讨论范围内,根本不适用于最短路径

    其次,正确地解释了BFS在带有圈的加权图上失败的原因,并建议使用优先级队列替换队列,如果找到到节点的新的较短路径,则允许松弛

    然而,在加权有向无环图(加权图)上,Dijkstra的是过杀的,通过按拓扑顺序松弛每个顶点,可以在
    O(|V|+|E |)
    时间中找到单源最短路径。这种方法也适用于具有负权重边的DAG

    下面是高级算法:

    distance={V:V在顶点中的无穷大}
    前置={V:顶点中的V无}
    对于拓扑排序中的U(顶点):
    对于相邻的V(U):
    如果距离[V]>距离[U]+边缘重量(U,V):#放松边缘
    距离[V]=距离[U]+边缘重量(U,V)
    前辈[V]=U
    
    资料来源:


    谢谢你,但我有一个疑问。您解释了Dijkstra在上述示例中的工作方式,它选择了从A->C到C的路径,因为它具有到C的最低边权重。假设,来自C->B的边的权重为4,并且存在来自A->D(权重3)和D->B(权重1)的边。按照你说的,边A->C和C->B首先被穿过,对吗?然后,我猜A->D和D->B的边必须被穿过,即使B已经被看到,否则我们将错过最短路径。那么,我们怎么能忽视这条道路呢?我想你在第三点提到了这一点。如果我错了,请纠正我。。Thanks@user2125722将首先遍历A->C,因为它是权重最低的边,然后是A->B和A->D,然后是D->B,然后是C->B。如果您不明白为什么会出现这种情况,请尝试单步遍历此图算法的伪代码。@user2125722请注意,在Dijkstra的算法中看到的定义略有不同。我更新了代码以更清楚地反映实际发生的情况。谢谢,我现在就知道了。因此,在Dijkstra中,我们检查每一条路径,但按照最短的看不见权重的顺序,对吗?@user2125722是的,您从起始节点开始几条路径,并每次扩展最短路径/将其拆分为多条路径。由于到目前为止,最短路径始终是先处理的,因此无论该路径上有多少条边,最终都会找到到达目的地的最短路径。谢谢,这是可以做到的,但在权重很大的情况下,这是不可行的,对吗?@partiallyfinit我知道了。谢谢:D@Lrrr您在回答中提到时间复杂度为O(V*M),但它是否会像PartiallyFinite提到的那样依赖于边的数量?您无法使用DFS来查找最短路径,即使在未加权的图中;BFS可以做到这一点。