請不要輕易點擊標題算法
一個能夠在有負邊的圖上使用的多源最短路算法spa
時間複雜度$O(n \cdot m \cdot log \ m+n \cdot m)$code
空間複雜度$O(n+m)$get
這個神奇的算法綜合利用了Dijkstra算法和Bellman-Ford算法(不要慌,雖然有負邊但Dijkstra能夠跑!)test
在開始講解以前,咱們將其與floyd進行比較di
時間複雜度$O(n^3)$時間
空間複雜度$O(n^2)$co
能夠看出,$floyd$複雜度與$m$無關 , 可見$floyd$適用於稠密圖的最短路,而$Johnson$算法則是適用於稀疏圖最短路acm
$$\ $$ps
$$\ $$
$$ \ $$
$$ \ $$
我對該算法的理解
限制條件:沒有負環便可
在有負權邊的圖上,$Dijkstra$的轉移受到限制,咱們須要進行必定處理
核心 : 將邊權$reweight$,保證邊權非負後,便可跑$n$遍$Dijkstra$,複雜度穩定$n \cdot m \cdot log \ m$(相較於SPFA來講穩定不少)
$$\ $$
1.創建超級源點0號節點,向$1 - n$號節點創建邊權爲0的有向邊
2.利用Bellman-Ford(或SPFA)求得$dis[0][1..n]$
3.將邊$(u,v,w)$加上$dis[0][u]-dis[0][v]$
4.將Dijkstra獲得的路徑$dis[u][v]$加上$dis[0][v]-dis[0][u]$還原
$$\ $$
關於Reweight的正確性
----$Step 3.$根據三角不等式$dis[v]<=dis[u]+w$,移項獲得$w+dis[u]-dis[v] \ge 0$,故Reweight後邊權非負
----$Step4.$對於一條最短路$\lbrace p_1,p_2,..,p_k\rbrace$,Reweight後更改的權值即$dis[p1]-dis[p2]+dis[p2]-dis[p3]...-dis[p_k]$
即$dis[0][v]-dis[0][u]$
----更改後 路徑保留的完整性 : 因爲對於任意一條路徑$dis[u][v]$,它更改的值都是一個常量$dis[0][v]-dis[0][u]$,不管路徑如何變動,都不影響這個常量的存在,因此原來的最短路依然保留
(固然個人證實含糊如放屁)
因此咱們能夠直接用這個算法解決一些特殊的問題