算法与数学基础 · 第 3 期

最短路径 不止一种

BFS / Dijkstra / Floyd · 各在哪翻车

BFS、Dijkstra、Floyd 都在求最短路径,但适用场景完全不同:无权图用 BFS,正权图用 Dijkstra,全源最短路用 Floyd。负权边会让 Dijkstra 给出错误答案,稠密图会让 Floyd 占满内存——选错算法,不是慢,是错。
⏱ 约 11 分钟 🎯 用过 Dijkstra 但没想过它边界的人 📦 源:OI-wiki · 最短路

01一个反共识:最短路算法不是"越高级越好"

很多人觉得 Floyd 比 Dijkstra 高级、Dijkstra 比 BFS 高级,所以都该用 Floyd。错。三种算法解决的是不同问题,用错不是慢,是错。

BFS | 无权 · Dijkstra | 正权 · Floyd | 全源

BFS 把每条边当权重 1,用队列一层层扩散,O(V+E)。Dijkstra 用优先队列每次取最小距离的点,O((V+E)logV),但假设边权非负——一旦有负权边,它"贪心地"锁定一个点后不再回头,会给出错误答案。Floyd 是三重循环求所有点对的最短路,O(V³),空间 O(V²),V 一大就爆内存。

选错最短路算法,
不是慢,是错。
灏天文库 · 算法与数学基础 P.14

02三种算法对比演示:同一张图,不同走法

选算法和图类型,点"运行",看从源点 A 到终点 G 的最短路径。注意有负权图上 Dijkstra 会给出错误结果。

🗺️ 最短路径算法对比
同一张图,不同算法,看路径与正确性差异。
点"运行"看结果。

03负权边为什么会让 Dijkstra 翻车

Dijkstra 的核心假设是:一个点一旦被"确定"最短距离,就不会再变。这依赖"边权非负"——因为只有非负,后续路径才不会让已确定的距离变小。

有负权边时这个假设崩了:A→B 距离 5 被锁定后,A→C→B 这条路可能因为 C→B 是 −3 而变成 4,但 Dijkstra 已经不会回头改 B 了。负权图要用 Bellman-Ford 或 SPFA,它们允许"松弛"已确定的点,代价是时间从 O((V+E)logV) 变成 O(VE)。

BFS

无权图

O(V+E),队列扩散。改不了权重,遇到带权图就废。

Dijkstra

正权图

O((V+E)logV),堆优化。负权边直接给错答案。

Floyd

全源最短路

O(V³),求所有点对。V>500 就别用了。

Bellman-Ford

含负权

O(VE),能检测负环。慢但正确。

Dijkstra 的"确定",
靠的是非负。
灏天文库 · 算法与数学基础 P.16

04带走这套清单

✅ 最短路 5 条可执行规则

  1. 先看边权:无权用 BFS,正权用 Dijkstra,有负权用 Bellman-Ford。
  2. 单源用 Dijkstra,全源用 Floyd(小图)或跑 n 次 Dijkstra(大稀疏图)。
  3. Dijkstra 遇到负权边会静默出错,务必在输入时校验边权。
  4. Floyd 空间 O(V²),V>500 考虑换 Johnson 或多次 Dijkstra。
  5. 判断负环:Bellman-Ford 跑 V 轮还能松弛,就有负环。
先看边权,
再选算法。
灏天文库 · 算法与数学基础 P.17