dan*_*oll 6 algorithm dijkstra breadth-first-search path-finding
如果存在一个加权图 G,并且所有权重都是0,那么 Dijkstra 算法是否仍然找到最短路径?如果是这样,为什么?
根据我对算法的理解,如果没有边权重,Dijsktra 的算法将像正常的BFS一样运行,但我希望得到一些澄清。
0根据算法的定义,Dijkstra 本身在权重方面没有问题。它只会在负权重时出现问题。
因为在每一轮中,Dijkstra 都会结算一个节点。如果您稍后发现负权重边,这可能会导致通往该已解决节点的路径更短。然后需要使节点不稳定,这是 Dijkstras 算法不允许的(并且会破坏算法的复杂性)。如果你看一下实际的算法和一些插图,就会很清楚。
Dijkstra 在这种全零图上的行为与所有边都具有不同但相同的值一样1(结果最短路径长度除外)。Dijkstra 将简单地访问所有节点,没有特定的顺序。基本上,就像一个普通的广度优先搜索。
看看维基百科的算法描述:
1 function Dijkstra(Graph, source):
2
3 create vertex set Q
4
5 for each vertex v in Graph: // Initialization
6 dist[v] ? INFINITY // Unknown distance from source to v
7 prev[v] ? UNDEFINED // Previous node in optimal path from source
8 add v to Q // All nodes initially in Q (unvisited nodes)
9
10 dist[source] ? 0 // Distance from source to source
11
12 while Q is not empty:
13 u ? vertex in Q with min dist[u] // Node with the least distance
14 // will be selected first
15 remove u from Q
16
17 for each neighbor v of u: // where v is still in Q.
18 alt ? dist[u] + length(u, v)
19 if alt < dist[v]: // A shorter path to v has been found
20 dist[v] ? alt
21 prev[v] ? u
22
23 return dist[], prev[]
Run Code Online (Sandbox Code Playgroud)
负值的问题在于行15和17。当您删除 node 时u,您就解决了它。也就是说,你说到这个节点的最短路径现在是已知的。但这意味着您不会u再次将其视为17某个其他节点的邻居(因为它不再包含在其中Q)。
对于负值,您以后可能会找到到该节点的较短路径(由于负权重)。您需要u在算法中再次考虑并重新执行所有依赖于之前最短路径的计算u。因此,您需要添加u从Q该节点中删除的每个其他节点都u在其最短路径上返回到Q.
特别是,您需要考虑可能通向目的地的所有边,因为您永远不知道某些讨厌的-1_000_000加权边隐藏在哪里。
下面的例子说明了这个问题:
Dijkstra 会将红色路径声明为从A到 的最短路径C,长度为0。但是,还有一条更短的路径。它被标记为蓝色,长度为99 - 300 + 1 = -200。
使用负权重,您甚至可以创建更危险的场景,即负循环。这是图中总权重为负的循环。然后你需要一种方法来停止一直沿着循环移动,无休止地降低你当前的体重。
在无向图中,0可以消除带权重的边并合并节点。它们之间的最短路径将始终具有 length 0。如果整个图只有0权重,那么这个图就可以合并到一个节点上。每个最短路径查询的结果很简单0。
如果在两个方向上都有这样的边,则有向图也是如此。如果没有,您将无法进行该优化,因为您会更改节点的可达性。