BFS / Dijkstra / Floyd · 各在哪翻车
很多人觉得 Floyd 比 Dijkstra 高级、Dijkstra 比 BFS 高级,所以都该用 Floyd。错。三种算法解决的是不同问题,用错不是慢,是错。
BFS 把每条边当权重 1,用队列一层层扩散,O(V+E)。Dijkstra 用优先队列每次取最小距离的点,O((V+E)logV),但假设边权非负——一旦有负权边,它"贪心地"锁定一个点后不再回头,会给出错误答案。Floyd 是三重循环求所有点对的最短路,O(V³),空间 O(V²),V 一大就爆内存。
选算法和图类型,点"运行",看从源点 A 到终点 G 的最短路径。注意有负权图上 Dijkstra 会给出错误结果。
Dijkstra 的核心假设是:一个点一旦被"确定"最短距离,就不会再变。这依赖"边权非负"——因为只有非负,后续路径才不会让已确定的距离变小。
有负权边时这个假设崩了:A→B 距离 5 被锁定后,A→C→B 这条路可能因为 C→B 是 −3 而变成 4,但 Dijkstra 已经不会回头改 B 了。负权图要用 Bellman-Ford 或 SPFA,它们允许"松弛"已确定的点,代价是时间从 O((V+E)logV) 变成 O(VE)。
O(V+E),队列扩散。改不了权重,遇到带权图就废。
O((V+E)logV),堆优化。负权边直接给错答案。
O(V³),求所有点对。V>500 就别用了。
O(VE),能检测负环。慢但正确。