交互式图论学习
交互式图论学习
Guest User
Using app without sign in
含负权边的最短路径计算器
找到最短路径并检测负权重环
选择算法并生成步骤以开始可视化
Bellman-Ford 算法解决可能包含负边权的图上的单源最短路径问题,这是 Dijkstra 无法处理的。它还能检测负环,即总权重小于零的环,负环会使最短路径无定义。
Bellman-Ford 对图中每条边松弛 V 减 1 次,其中 V 是节点数。每一轮将正确的最短距离向外传播一跳,因此经过 V 减 1 轮后,所有至多 V 减 1 条边的最短路径都已确定。最后额外一轮检查是否仍有边可松弛;若有,则图中存在从源点可达的负环。运行时间为 O(VE),比 Dijkstra 慢但通用得多。
Bellman-Ford 用于 RIP 等距离向量路由协议、汇率变为负对数权重时的货币套利检测,以及任何可能有负成本的规划问题。面试题常考查候选人是否清楚何时 Dijkstra 失效而必须用 Bellman-Ford。
Bellman-Ford 是一个用精巧换取通用性的最短路径算法。没有优先队列,也没有顺序上的抉择,只有对所有边的反复松弛。
BellmanFord(图, 源点):
对每个结点 v: dist[v] = 无穷大
dist[源点] = 0
重复 V - 1 次:
有改动 = 假
对每条边 (u, v, w):
若 dist[u] + w < dist[v]:
dist[v] = dist[u] + w
父结点[v] = u
有改动 = 真
若无改动: 退出 // 提前结束
// 额外一轮用于检测负环
对每条边 (u, v, w):
若 dist[u] + w < dist[v]:
报告存在可达的负环不变式是:第 i 轮之后,所有至多使用 i 条边的最短路径都已正确。由于无负环图中的最短路径至多使用 V - 1 条边,V - 1 轮即可全部确定。若第 V 轮仍能改进,说明某条路径可以无限变短,而这正是负环的含义。
从 A 出发,在一个含负权边、Dijkstra 会算错的图上运行 Bellman-Ford。边按下列固定顺序松弛。
示例图: 有向边 A 到 B (4)、A 到 C (5)、B 到 C (-3) 和 C 到 D (2)。
正确的距离是 A 0、B 4、C 1、D 3。仅仅一条负权边就足以让 Dijkstra 出错,这正是 Bellman-Ford 存在的理由。
时间: O(VE) · 空间: O(V)
算法执行 V - 1 轮,每轮把 E 条边各松弛一次,因此为 O(VE)。空间是每个结点一个距离和一个父指针,即 O(V),值得注意的是它与 E 无关。在 E 接近 V 的平方的稠密图上,时间趋近 O(V 的立方),这也是 Bellman-Ford 只用于确实存在负权重场合的原因。提前结束的检查会在某一轮没有任何改动时停止,在真实图上往往几轮就结束,尽管最坏情况仍是 V - 1 轮。
Bellman-Ford 严格比 Dijkstra 更通用,也严格更慢。只有确实需要它带来的能力时才选它。
| 替代算法 | 以下情况更合适 | 代价 |
|---|---|---|
| Dijkstra 算法 | 所有边权非负。快得多,是正确的默认选择。 | O((V + E) log V) |
| BFS | 图无权重,跳数即距离。 | O(V + E) |
| Floyd-Warshall | 你要的是所有点对之间的距离而非单源,且图较小或较稠密。 | O(V^3) |
| SPFA(队列优化的 Bellman-Ford) | 稀疏图上的负权重。实践中快得多,但最坏情况仍是 O(VE)。 | 最坏 O(VE) |
| Johnson 算法 | 稀疏图上带负权重的全源最短路径。先用一次 Bellman-Ford 重赋权,再从每个结点跑 Dijkstra。 | O(V·E + V^2·log V) |
阅读完整文章: Shortest Path Algorithms Explained
相关算法: 迪杰斯特拉算法, 弗洛伊德-沃歇尔算法, 环检测