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

贝尔曼-福特改进:有效吗?

陈斌蔚
2023-03-14

我正在努力改进Bellman-Ford算法的性能,我想知道改进是否正确。

我运行松弛部分不是V-1而是V次,并且我得到了一个涉及的布尔变量,如果在外循环的迭代过程中发生任何松弛,则将其设置为true。如果在n.迭代中没有发生松弛,其中n

我认为这可能会改善运行时,因为有时我们不必迭代V-1次来找到最短路径,而且我们可以更早地返回,而且它也比用另一块代码检查循环更优雅。

AdjacencyListALD graph;

int[] distTo;
int[] edgeTo;

public BellmanFord(AdjacencyListALD g)
{
    graph = g;
}

public int findSP(int source, int dest)
{

    // initialization

    distTo = new int[graph.SIZE];
    edgeTo = new int[graph.SIZE];

            for (int i = 0;i<graph.SIZE;i++)
            {
                distTo[i] = Integer.MAX_VALUE;
            }

            distTo[source] = 0;

    // relaxing V-1 times + 1 for checking negative cycle = V times

    for(int i = 0;i<(graph.SIZE);i++)
    {
        boolean hasRelaxed=false;

        for(int j = 0;j<graph.SIZE;j++)
        {
            for(int x=0;x<graph.sources[j].length;x++)
            {
                int s = j;
                int d = graph.sources[j].get(x).label;
                int w = graph.sources[j].get(x).weight;

                if(distTo[d] > distTo[s]+w)
                {
                    distTo[d] = distTo[s]+w;
                    hasRelaxed = true;                      
                }
            }
        }
        if(!hasRelaxed)
            return distTo[dest];

    }
    System.out.println("Negative cycle detected");
    return -1;


}

共有1个答案

时修贤
2023-03-14

关于测试必要性的良好评论。这是给定的。但是它没有解决潜在的问题,即OP对贝尔曼-福特的修改是否构成对算法的改进。答案是,是的,正如巴赫在评论中指出的,这实际上是一个众所周知的进步。

OP的观察是,如果在任何松弛迭代中,没有任何东西松弛,那么在随后的迭代中就不会有任何变化,因此我们可以停止。绝对正确。对分配给顶点的值没有外部影响。唯一更新这些值的是松弛步骤本身。如果它在任何迭代中找不到任何可做的事情,那么就不可能有什么可做的事情从以太中实现。因此我们可以终止。

这不会影响算法的复杂性,也不会帮助处理最坏情况图,但在实践中可以减少实际运行时间。

至于再运行一次松弛(|V|次而不是通常的|V|-1),这只是声明松弛步骤后负循环检查的另一种方式。这只是另一种说法,当我们通过运行|V|-1松弛迭代终止时,我们需要看看是否还可以计算任何改进,这揭示了一个负循环

一句话:OP的方法是合理的。现在,是的,测试代码。

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

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

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

  • 我一开始从维基百科上得到著名的颜教授对Bellman-Ford算法的优化,后来我在几本教科书的练习部分发现了同样的改进(例如,这是Cormen中的24-1问题和Sedgewick的“算法”中的网络练习N5)。 以下是改进: Yen的第二个改进首先在所有顶点上指定一些任意的线性顺序,然后将所有边集划分为两个子集。第一个子集Ef包含所有边(vi,vj),因此i 不幸的是,我没有找到这个界| V |/2

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

  • 我已经成功地实现了Bellman-Ford,当边具有负权重/距离时,找到最短路径的距离。我无法让它返回所有最短路径(当最短路径有联系时)。我设法用Dijkstra获得所有最短的路径(给定的一对节点之间)。贝尔曼-福特有可能吗?(只是想知道我是否在浪费时间)