gpt4 book ai didi

algorithm - Bellman-Ford 的负循环

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:10:03 30 4
gpt4 key购买 nike

在具有 V 个节点和 E 条边的有向图中,Bellman-Ford 算法将每个顶点(或者更确切地说,从每个顶点发出的边)松弛 (V - 1) 次。这是因为从源到任何其他节点的最短路径最多包含 (V - 1) 条边。在第V次迭代中,如果一条边可以松弛,说明存在负循环。

现在,我需要找到被这个负循环“破坏”的其他节点。也就是说,一些不在负循环上的节点现在与源的距离为负无穷大,因为从源到位于负循环中的节点的路径上有一个或多个节点。

实现此目的的一种方法是运行 Bellman-Ford 并记录负循环上的节点。然后,从这些节点运行 DFS/BFS 以标记其他节点。

但是,为什么我们不能在不求助于 DFS/BFS 的情况下运行 Bellman-Ford 2 * (V - 1) 次来检测此类节点?如果我的理解是正确的,那么将所有顶点放松 2 * (V - 1) 次应该允许负循环将它们的值“传播”到所有其他连接的节点。

其他详细信息:我在解决这个在线问题时遇到了这种情况:https://open.kattis.com/problems/shortestpath3

我使用的 Java 代码(以及此处未显示的 BFS/DFS)如下:

  // Relax all vertices n - 1 times.
// And relax one more time to find negative cycles
for (int vv = 1; vv <= n; vv++) {
// Relax each vertex
for (int v = 0; v < n; v++) {
// For each edge
if (distTo[v] != (int) 1e9) {
for (int i = 0; i < adjList[v].size(); i++) {
int dest = adjList[v].get(i).fst;
int wt = adjList[v].get(i).snd;

if (distTo[v] + wt < distTo[dest]) {
distTo[dest] = distTo[v] + wt;

if (vv == n) {
isInfinite[v] = true;
isInfinite[dest] = true;
}
}
}
}
}
}

最佳答案

考虑一个带有 N=4, M=5 的图:

A -> B weight 1000
A -> C weight 1000
C -> D weight -1
D -> C weight -1
D -> B weight 1000

设 A 为源,B 为目的地。

现在明显有一个负循环(C <-> D) .但是无论我们运行算法 N 次还是 2N 次甚至 3N 次,从 A 到 B 的最短路径仍然是 1000。由于每次使用负循环只会减少一点距离,因此不会传播到我们期望的其他节点。

一旦确定影响节点的循环,解决方案就是将距离标记为负无穷大。这样,负循环“优先于”通过其他节点的其他最短路径。

您真诚的,
一位在这个问题上花费了大量时间的编码人员。

关于algorithm - Bellman-Ford 的负循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50886584/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com