最近,我看到了贝尔曼·福特的问题和一些事实如下:
我们知道bellman-ford算法在每个步骤中检查所有边,对于每个边,如果,d(v)
对于在具有n
顶点的图G中查找顶点s
的所有最短路径,此算法在k之后终止
以下事实是真实的。
来自
s
的所有最短路径中的边数最多为k-1
在这本书中,我们有3个BFord的实现(一些优化)。我的问题是,如果我们同时有松弛,应该使用这些算法中的哪一个,通过使用它,上述事实应该是正确的?或者不是一般的上述事实是否属实?
最后的算法,BellmanFordFinal(s)
是上述三种算法的优化版本。
优化1:
在这本书中,传奇人物杰夫·埃里克森教授解释了贝尔曼提出的原始算法是如何通过去除算法中最后3行的缩进来优化的。
因为最外层的迭代考虑每个边u-
优化2:
在最后两行中,索引
i-1
已更改为i
,这使算法能够更快地正确计算值(最短路径)。
优化3:
二维DP阵列被转换为一维,因为它是不必要的。
因此,请使用最终算法,标题为
BellmanFordFINE(s)
。
事实上,我们需要在
N-1
时间内运行最外层的循环,这始终是正确的,并且与任何实现无关,因为在线性图的情况下,从源到目标的最长最短路径将是N-1
,其中N是图中的节点数。
回答您对
k-1的担忧
从s开始的所有最短路径中的边数最多为k-1
上述语句取决于算法的实现。
如果添加If条件以在没有任何边进一步松弛时打断最外面的循环,则此语句为false。
否则是真的。
看看我在https://cp-algorithms.com/graph/bellman_ford.html上发现的以下实现:
void solve()
{
vector<int> d (n, INF);
d[v] = 0;
for (;;)
{
bool any = false;
for (int j=0; j<m; ++j)
if (d[e[j].a] < INF)
if (d[e[j].b] > d[e[j].a] + e[j].cost)
{
d[e[j].b] = d[e[j].a] + e[j].cost;
any = true;
}
if (!any) break;
}
// display d, for example, on the screen
}
变量
any
用于检查它们是否在任何迭代中完成了任何松弛。如果没有做到,打破循环。
因此,可能会发生循环提前终止的情况,例如,当k=2且最长最短路径中的边数为3时。现在,3个
假设有一个具有
我们知道bellman-ford算法检查每一步中的所有边,如果, d(v) 然后更新d(v),使得w(u,v)是边(u,v)的权重,d(u)是顶点的最佳查找路径长度。如果在一个步骤中我们没有顶点更新,那么算法将终止。在假设该算法的情况下,求出了图G中顶点
我正在做一个有向图的项目,其中边的权重都依赖于变量x。我试图找到x的最小值,这样我的图就不包含任何正权重的回路。 我的问题是——这可能很愚蠢,但我不明白如何——:我如何使用改良的贝尔曼-福特来检查正电路而不是负电路的存在? 谢谢。
我对贝尔曼-福特做了一点修改,这样它只能“有用”放松。也就是说,d(v)的松弛被更新了。 现在,如果所有最短路径最多有k条弧。那么最坏情况下的运行时是O(V*k),因为在这个智能版本中我们只经过k个弧。这比原来的O(V*E)快一点,因为| k| 有谁能告诉我一种图的类型,这种改进的版本并不比原来的Bellman-Ford算法好?也就是说,最佳情况下的性能是O(V*E)
有了贝尔曼-福特的算法,稍有改变:在第7行,我们把
我在试图理解这个算法是如何工作的。 给定一个问题,搜索从源s到图中所有顶点的路径, 我想我必须这样做: 我的问题是: 我的程序是好的还是我必须改变它。 当我必须检查是否存在负循环时?非常感谢。