Dijkstra 算法可以在权重为 0 的图上工作吗?
Can Dijkstra's Algorithm work on a graph with weights of 0?
如果存在加权图 G
,并且所有权重都是0
,Dijkstra算法是否还是找最短路径?如果是,为什么?
根据我对算法的理解,如果没有边权重,Dijsktra 的算法将 运行 像正常的 BFS 一样,但我希望得到一些说明。
说明
Dijkstra 本身对 0
权重没有问题,根据算法的定义。它只会在 negative 权重时出现问题。
因为在每一轮中 Dijkstra 都会解决一个节点。如果您稍后发现负加权边,这可能会导致 更短的路径 到该已解决的节点。然后节点需要未解决,Dijkstras 算法不允许(这会破坏算法的复杂性)。如果你看一下实际的算法和一些插图,就会清楚。
Dijkstra 在这样一个 全零 图上的行为与所有边都具有不同但相同的值相同,例如 1
(除了由此产生的最短路径长度)。 Dijkstra 将简单地访问所有节点,没有特定的顺序。基本上,就像一个普通的 Breadth-first 搜索.
详情
看看算法描述来自Wikipedia:
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[]
负值的问题在于第 15
和 17
行。当您删除节点 u
时,您 解决 它。也就是说,你说到这个节点的最短路径现在是已知的。但这意味着您不会再将 17
行中的 u
视为某个其他节点的邻居(因为它不再包含在 Q
中)。
对于负值,您稍后可能会发现到该节点的较短路径(由于负权重)。您需要在算法中再次考虑 u
和 re-do 所有依赖于先前到 u
的最短路径的计算。因此,您需要添加 u
以及从 Q
中删除的所有其他节点,这些节点在其最短路径上具有 u
返回 Q
.
特别是,您需要考虑 所有可能通向目的地的边,因为您永远不知道某些讨厌的 -1_000_000
加权边隐藏在哪里。
下面的例子说明了这个问题:
Dijkstra 将声明红色路径为从 A
到 C
的最短路径,长度为 0
。但是,还有一条更短的路径。它被标记为蓝色,长度为 99 - 300 + 1 = -200
.
使用负权重,您甚至可以创建更危险的场景,负循环。这是图中总权重为负的循环。然后你需要一种方法来停止一直沿着循环移动,无休止地降低你当前的体重。
备注
在无向图中,权重为 0
的边可以 消除 并且节点可以 合并 。它们之间的最短路径的长度始终为 0
。如果整张图只有0
个权重,那么只需要将图合并到一个节点即可。每个最短路径查询的结果只是 0
.
如果在两个方向上都有这样的边,那么对于有向图也是如此。如果不是,则无法像更改 reach-ability 节点那样进行优化。
如果存在加权图 G
,并且所有权重都是0
,Dijkstra算法是否还是找最短路径?如果是,为什么?
根据我对算法的理解,如果没有边权重,Dijsktra 的算法将 运行 像正常的 BFS 一样,但我希望得到一些说明。
说明
Dijkstra 本身对 0
权重没有问题,根据算法的定义。它只会在 negative 权重时出现问题。
因为在每一轮中 Dijkstra 都会解决一个节点。如果您稍后发现负加权边,这可能会导致 更短的路径 到该已解决的节点。然后节点需要未解决,Dijkstras 算法不允许(这会破坏算法的复杂性)。如果你看一下实际的算法和一些插图,就会清楚。
Dijkstra 在这样一个 全零 图上的行为与所有边都具有不同但相同的值相同,例如 1
(除了由此产生的最短路径长度)。 Dijkstra 将简单地访问所有节点,没有特定的顺序。基本上,就像一个普通的 Breadth-first 搜索.
详情
看看算法描述来自Wikipedia:
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[]
负值的问题在于第 15
和 17
行。当您删除节点 u
时,您 解决 它。也就是说,你说到这个节点的最短路径现在是已知的。但这意味着您不会再将 17
行中的 u
视为某个其他节点的邻居(因为它不再包含在 Q
中)。
对于负值,您稍后可能会发现到该节点的较短路径(由于负权重)。您需要在算法中再次考虑 u
和 re-do 所有依赖于先前到 u
的最短路径的计算。因此,您需要添加 u
以及从 Q
中删除的所有其他节点,这些节点在其最短路径上具有 u
返回 Q
.
特别是,您需要考虑 所有可能通向目的地的边,因为您永远不知道某些讨厌的 -1_000_000
加权边隐藏在哪里。
下面的例子说明了这个问题:
Dijkstra 将声明红色路径为从 A
到 C
的最短路径,长度为 0
。但是,还有一条更短的路径。它被标记为蓝色,长度为 99 - 300 + 1 = -200
.
使用负权重,您甚至可以创建更危险的场景,负循环。这是图中总权重为负的循环。然后你需要一种方法来停止一直沿着循环移动,无休止地降低你当前的体重。
备注
在无向图中,权重为 0
的边可以 消除 并且节点可以 合并 。它们之间的最短路径的长度始终为 0
。如果整张图只有0
个权重,那么只需要将图合并到一个节点即可。每个最短路径查询的结果只是 0
.
如果在两个方向上都有这样的边,那么对于有向图也是如此。如果不是,则无法像更改 reach-ability 节点那样进行优化。