核心代码:
for (int k = 1; k <= n - 1; ++k){
for (int i = 1; i <= m; ++i){
if(dis[v[i]] > dis[u[i]] + w[i])
dis[v[i]] = dis[u[i]] + w[i];
}
}
上面的代码外层循环一共循环了n - 1次(n为顶点个数), 内层循环循环了m次(m为每一条边),即枚举每一条边。dis数组的作用与Dijkstra算法一样,是用来记录源点到其余各个顶点的最短路径的。u、v、w三个数组是用来记录边的信息的。例如:第i条边存储在u[i]、v[i]、和w[i]中, 表示从顶点u[i]到顶点v[i]这条边(u[i]->v[i])权值为w[i]。
if(dis[v[i]] > dis[u[i]] + w[i])
dis[v[i]] = dis[u[i]] + w[i];
上面这行代码的意思是:看看能否通过u[i]->v[i](权值为w[i])这条边,使得1号顶点到v[i]号顶点的距离(dis[u[i]])加上u[i]->v[i](权值为w[i])这条边的值是否会比原先1号顶点到v[i]号顶点的距离(dis[v[i]])要小。这一点其实是与Dijkstra算法中的“松弛”操作是一样的。现在我们要把所有的边松弛一遍,代码如下:
for (int i = 1; i <= m; ++i){
if(dis[v[i]] > dis[u[i]] + w[i])
dis[v[i]] = dis[u[i]] + w[i];
}
把每条边都松弛一遍之后会有什么效果呢?现在来举个例子。求下图1号顶点到其余各点的最短路径。

我们还是用一个dis数组来存储1号顶点到所有顶点的距离。

上方右图中每个顶点旁的值(带下划线的数字)为该顶点的最短路“估计值”(当前1号顶点到该顶点的距离),即数组dis中对应的值。根据边给出的顺序,先来处理第一条边“2 3 2”(2->3,权值为2,通过这条边进行松弛)。即判断dis[3]是否大于dis[2] + 2。
本文详细解析了Bellman-Ford算法,介绍了如何处理图中的负权边,并通过实例展示了算法的运行过程。核心思想是在n-1轮迭代中对每条边进行松弛操作,以找到最短路径。同时,文章指出在n-1轮后仍能松弛说明存在负权回路,并讨论了算法的优化策略。
最低0.47元/天 解锁文章
384

被折叠的 条评论
为什么被折叠?



