当前位置: 首页 > 知识库问答 >
问题:

贝尔曼福特的负周期

郑宇
2023-03-14

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

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

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

然而,为什么我们不能运行Bellman-Ford 2*(V-1)次来检测这样的节点,而不诉诸DFS/BFS?如果我的理解是正确的,放松所有顶点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;
            }
          }
        }
      }
    }
  }

共有2个答案

穆智刚
2023-03-14

在经典情况下,所有节点“在”一个负长度循环上与源有一个任意的小距离。因此,在v-1之后的每次迭代中,从源到这些节点的路径会变得更小。该任务要求您为所有此类节点返回-infinity。

您可以使用Bellman-Ford算法的修改版本来标记所有此类节点的距离,例如-infinity,并运行它v-1次,以将-infinity传播到连接到循环的所有其他节点。但与仅从循环中的节点运行DFS或BFS相比,这需要大量额外的时间。

慕河
2023-03-14

考虑图< <代码> 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

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

您诚挚的,
一位在这个问题上花费了大量时间的程序员同事。

 类似资料:
  • 我已经实现了Bellman-Ford算法来检测图中的负循环。值得注意的是,图中的每条边都有一个倒数,因此如果存在一条边,它可以从

  • 我知道Bellman-Ford算法最多需要| V |-1次迭代才能找到最短路径,如果图不包含负权重循环。有没有办法修改Bellman-Ford算法,使其在1次迭代中找到最短路径?

  • 我这里有一个更聪明的贝尔曼福特版本: 有人能想到一种图,对于这种图,该算法的时间复杂度下限为(V*E),其中V=#顶点,E=#边 我想看看这个陷阱在哪里。

  • 我有一个家庭作业来实现贝尔曼·福特的算法,并在一些图形上测试它。我实现了这个算法,在3张图中的2张上测试了它,它是有效的。但是在第三个图中,我在调用函数时没有输出。 此部分创建图形及其边。函数将顶点数和边数作为参数。 这是添加新边的函数。 下面是我对Bellman Ford算法的实现。

  • 我一直试图通过以下资源来理解贝尔曼福特的正确实现:1 如果我们已经知道给定的加权有向图不包含一个圈(因此也没有负圈),是否遵循Bellman-Ford算法的正确实现? 我在上述实现中遇到的第一个问题是,如果图中只有两个节点具有从源节点到目标节点的定向边,那么需要修改for的第一个

  • 我正在努力改进Bellman-Ford算法的性能,我想知道改进是否正确。 我运行松弛部分不是V-1而是V次,并且我得到了一个涉及的布尔变量,如果在外循环的迭代过程中发生任何松弛,则将其设置为。如果在n.迭代中没有发生松弛,其中n 我认为这可能会改善运行时,因为有时我们不必迭代V-1次来找到最短路径,而且我们可以更早地返回,而且它也比用另一块代码检查循环更优雅。