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

贝尔曼-福特负周期前身不存在

谈琛
2023-03-14

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

我的问题是在导航前置链时(存储在dictionarypred中)。源顶点似乎从来没有前置顶点,因此当我在负循环检查中循环遍历每个顶点时,会引发异常,因为pred从来没有源顶点的条目。

这是什么意思?图中似乎有一个负循环,但是如果没有任何东西先于源顶点,并且源顶点被“包括”在检测到的负循环中,那么真的有一个循环可以开始吗?

private List<Vertex> BellmanFord( Vertex source )
{
  var dist = new Dictionary<Vertex, double>();
  var pred = new Dictionary<Vertex, Vertex>();

  // Initialize
  foreach( var vertex in Vertices )
    dist[ vertex ] = double.MaxValue;
  dist[ source ] = 0;

  // Relax
  foreach( var vertex in Vertices )
    foreach( var edge in Edges )
      Relax( edge, ref dist, ref pred );

  // Check for negative cycles
  foreach( var edge in Edges )
  {
    if( dist[ edge.From ] != double.MaxValue )
      if( HasCycle( edge, ref dist )
      {
        var cycle = new List<Vertex>();
        var vertex = edge.From;

        while( vertex == edge.To )
        {
          cycle.Add( vertex );
          vertex = pred[ vertex ];
        }

        cycle.Add( edge.To );
        return cycle;
      }
  }

  return new List<Vertex>(); // No cycle
}

private void Relax( Edge edge, ref Dictionary<Vertex, double> dist, ref Dictionary<Vertex,Vertex> pred )
{
  if( dist[edge.From] == double.MaxValue )
    return;

  var newDist = dist[ edge.From ] + edge.Weight;
  if( newDist < dist[ edge.To] )
  {
    dist[ edge.To ] = newDist;
    pred[ edge.To ] = edge.From;
  }
}

private bool HasCycle( Edge edge, ref Dictionary<Vertex, double> dist )
{
  return dist[edge.To] > dist[edge.From] + edge.Weight;
}

为了更好地度量,每个边的权重计算为-1*Math。日志(值)


共有1个答案

丁雅惠
2023-03-14

据我所知,观察到的行为并不表明您的实现中存在缺陷。Bellman-Ford算法能够得出结论,存在一个负长度的循环;这并不意味着可以找到每一个负长度的循环。Floyd-Warshall算法可能更适合这种情况。两种算法解决问题的不同公式;第一种方法解决了单源最短路径问题,第二种方法解决了全对最短路径问题。

 类似资料:
  • 在具有V节点和E边的有向图中,Bellman-Ford算法将每个顶点(或者更确切地说,每个顶点的边)松弛(V-1)次。这是因为从源到任何其他节点的最短路径最多包含(V-1)条边。在第V次迭代中,如果边可以松弛,则表示存在负循环。 现在,我需要找到被这个负循环“摧毁”的其他节点。也就是说,由于从源到位于负循环中的节点的路径上有一个或多个节点,因此一些不在负循环中的节点现在与源的距离为负无穷远。 实现

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

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

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

  • 经过大量谷歌搜索,我发现大多数消息来源说迪克斯特拉算法比贝尔曼-福特算法“更有效”。但是在什么情况下Bellman-Ford算法比Dijkstra算法更好呢? 我知道“更好”是一个宽泛的说法,所以具体来说,我指的是速度和空间,如果适用的话。当然,在某些情况下,贝尔曼-福特方法比迪克斯特拉方法更好。

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