以此纪念我学会该算法。
Johnson 全源最短路
Johnson 全源最短路可以用来求有负权的图的全源最短路。
步骤
-
新建一个虚拟 0 0 0 号节点。
-
在节点 0 0 0 至节点 i ( i ∈ [ 1 , n ] ) i(i \in [1,n]) i(i∈[1,n]) 中插入一条权值为 0 0 0 的有向边。
-
使用 Bellman-ford 算法(SPFA 也可)计算节点 0 0 0 到其它节点的最短路径(顺便判断负环),记为 H i H_i Hi。
-
将原图每条边的权值 w u , v w_{u,v} wu,v 改为 w u , v + H u − H v w_{u,v}+H_u-H_v wu,v+Hu−Hv。
-
跑 n n n 轮 Dijkstra 算法,求出全源最短路。
复杂度: O ( 1 ) + O ( n ) + O ( n m ) + O ( m ) + n ∗ O ( ( n + m ) log n ) = O ( n m log n ) O(1)+O(n)+O(nm)+O(m)+n*O((n+m)\log n)=O(nm\log n) O(1)+O(n)+O(nm)+O(m)+n∗O((n+m)logn)=O(nmlogn)