Bellman-Ford算法和SPFA学习笔记
Bellman-Ford
前置知识
- 首先你需要知道图论最核心的一个思路——松弛。
- 他是啥呢?笔者当时学的时候也花了亿堆时间理解它,就是假如我们现在有一些边,如图:

简单来说,松弛就是不断的更新两个点的距离使得它比之前的答案更优。
在这张图片里,我们将要松弛的 个节点为 , 为源点
那么它的原始距离是 ,那么如果我更新了他的一条路径(松弛成功),这个路径的边权和一定是要比 小的。
好,那我们先来遍历和 点有直接连边的节点。
-
先看 那我们知道现在点 到点 的距离是 ,那因为 到点 的距离是 ,所以 到 经过点 的距离就是 ,很显然,这个答案是比当前已知答案要差的。所以这次松弛并没有成功,我们选择放弃当前绕路的边权和。
-
再看 那我们知道现在点 到点 的距离是 ,那因为 到点 的距离是 ,所以 到 经过点 的距离就是 ,这时候我们发现,这个答案是比当前已知答案要优的。所以这次松弛成功,我们选择更新当前绕路的边权和为 目前为止的最短路径。更新后的图如下:

-
最后看 那我们知道现在点 到点 的距离是 ,那因为 到点 的距离是 ,所以 到 经过点 的距离就是 ,很显然,这个答案是比当前已知答案要差的。所以这次松弛并没有成功,我们选择放弃当前绕路的边权和。
那么经过一轮松弛操作下来,我们最终所的结果就是—— 的最短路为 。
正题
如果你松弛理解好了,那么Bellman-Ford算法就是对于每一个点和源点进行松弛操作,如果答案更优,那么更新该点到源点的距离。
这样的松弛操作每次必然能确定 个点的最短路。那么我们的BellmanFord算法的轮数就是 轮。
换句话说,当一个有解的最短路使用BellmanFord求解时进行的 轮的操作都是没有意义的。那么如果该图无解呢?
判负环
- 如果一个有负环的图使用BF(BellmanFord)算法求解,每次进行一大轮的松弛都会导致更新,这会导致最短路随着轮数的增加越来越小,那么我们在用BF算法判断负环时只需要在 轮结束后再进行一轮松弛,如果最短路变了,那么该图有负环! 因为正常的图在第 轮过后无论在如何松弛都会失败,而有负环的图每次松弛都能更新最短路长度。
貌似BF算法比别的算法的有点就只有这一个
时间复杂度
- 这个算法的时间复杂度巨巨巨好算,是 ,( 是点数 是边数)。
模板
1 | /*Bellman-Ford算法板子*/ |
SPFA
- 对于上面的BF算法,我们会发现:在这一轮中每个店都要松弛,有好多店压根就没变,这岂不是太浪费时间了?!
- 那我们直接更新改变过的节点不就完了?!
- 他就是SPFA。我们把更改的节点入队,从队列中取节点进行松弛即可。
它死了
- 如果遇到节点巨巨巨巨稠密的图,SPFA会将一个节点入队入队入队入队——喜提TLE。
- 所以呢,如果没有负权边这边建议直接Dijkstra搞。
判断负环
- 如果一个点入队 次,那么就代表它被松弛了 次,即:有负环!
判断负环例题:P2850 [USACO06DEC] Wormholes G
1 | /*体面意思就是,从任意一点出发,走一圈之后回到这个点路径长度总和小于零的路径是否存在,这不就是判断负环吗?!*/ |
本博客所有文章除特别声明外,均采用 GNU GPL 3.0 许可协议。转载请注明来源 FrankWkd!

