1 算法背景与核心直觉
在单源最短路问题中,当图上存在负权边(甚至可能包含负权环)时,基于贪心的 dijkstra 算法便不再适用。
Bellman-Ford 算法直接基于动态规划与边的反复松弛,不仅能够正确处理负权边,还能有效检测图中是否存在从源点可达的负权环。
2 核心定理与证明
定理1: 最短路上的点数与边数界限
在一个无负环的图
- 点数不超过
; - 边数不超过
。
证明(反证法):
假设最短路径经过了超过
则整条路径可以表示为:
在路径中包含了一个起点与终点皆为
- 因为图
中不存在负环,所以该回路的权值和必为非负值( )。 - 如果我们将这个回路直接从路径中删去,得到新路径
: - 新路径的权值和必
原路径的权值和; - 这与“原路径是最短路径且必须包含该回路”的前提矛盾!
- 新路径的权值和必
因此,最短路径上一定不包含任何环,即必然是一条简单路径。
包含
3 松弛操作的定义
两个点
1:if then
2:
3:end if
4 算法核心过程与图解
Bellman-Ford 算法的核心在于:按轮次对图中的所有边进行整体松弛。
交互动画加载中...
4.1 轮次演进不变量
设源点为
核心归纳不变量:
在第
轮全局边松弛结束后, 的值至多等于“从源点 到 且经过边数不超过 条的最短路径长度”。
- 初始(
):只有经过 条边的源点自身距离为 ,其余不可达,不变量成立。 - 第
轮( ):枚举所有边,源点的一度邻居被松弛,得到了最多经过 条边的最短距离。 - 第
轮:任何最多经过 条边的最短路径,其最后一步一定形如一条边 ,且前缀路径最多经过 条边。由归纳假设, 在前 轮已经达到最优,因此本轮松弛必然能算出不超过 条边的最优 。
4.2 为什么只需要 轮?
根据定理1,在无负环的图上,任何点之间的最短路最多只包含
若在第
5 负环判定原理
如果在完成了
- 如果此时仍然存在某条边
满足 ; - 这说明存在一条能让距离更小的路径,其包含的边数至少为
条; - 边数
意味着该路径至少经过了 个顶点,根据抽屉原理必定存在环,且绕这个环能让总距离变小——这证明图中必然存在从源点可达的负权环!
6 算法步骤总结
- 初始化:
,其余点 。 - 进行至多
轮循环: - 遍历图中的所有
条边 ; - 若
且 ,则更新 ; - 若本轮未发生任何松弛,提前退出。
- 遍历图中的所有
- 再遍历一次所有边:
- 若仍能成功松弛,报告存在负环。
- 否则输出最短路数组
。
7 模板代码
#include <algorithm>
#include <iostream>
#include <vector>
const long long INF = (1LL << 60);
struct Edge {
int u, v;
long long w;
};
// 点编号为 1..n;返回 true 表示成功求得最短路,false 表示存在从源点可达的负环
bool bellman_ford(int n, const std::vector<Edge>& edges, int s, std::vector<long long>& dis) {
dis.assign(n + 1, INF);
dis[s] = 0;
// 运行至多 n - 1 轮松弛
for (int round = 1; round <= n - 1; ++round) {
bool changed = false;
for (const auto& e : edges) {
if (dis[e.u] == INF) continue; // 源点尚不可达,不能拿 INF 参与相加
if (dis[e.u] + e.w < dis[e.v]) {
dis[e.v] = dis[e.u] + e.w;
changed = true;
}
}
// 如果某一轮没有发生任何松弛,说明所有最短路已经确定,可以提前退出
if (!changed) break;
}
// 第 n 轮检测负环:若还能继续松弛,说明存在负环
for (const auto& e : edges) {
if (dis[e.u] == INF) continue;
if (dis[e.u] + e.w < dis[e.v]) {
return false; // 存在从 s 可达的负环
}
}
return true;
}
8 复杂度与对比
设点数为
- 时间复杂度:最坏情况下进行
轮松弛,每轮遍历全部 条边,时间复杂度为稳定 。 - 空间复杂度:只需要存边数组和
数组,空间复杂度为 。
若要对 Bellman-Ford 的每轮盲目扫描进行常数优化,只让距离变小的点去通知邻居,则演化出队列优化的版本:spfa。 更多负环的判定方法(点更新次数、DFS 版负环判定等),请参见章节:负环。
9 相关题解
暂无相关题解