1. 程式人生 > 其它 >Floyd 演算法學習筆記

Floyd 演算法學習筆記

Floyd演算法學習筆記(未完結)

前言

如有錯誤,歡迎各位 dalao 批評指出。

前置芝士:

1.鄰接矩陣(Floyd要用鄰接矩陣存圖)

2.動態規劃思想(最好學過,沒學過也沒有太大影響)

1. Floyd 所解決問題的型別

我們可以發現,如 Dijkstra,SPFA,Bellman Ford 一類的最短路演算法都是解決單源點最短路問題,也就是確定了起點或者終點來求最短路的問題。但是,我們發現,這些演算法解決多源點最短路問題,也就是有多個起點和終點的最短路問題 ,的效率太低。假設有 \(n\) 個點,\(m\) 條邊。解決多源最短路時,如果用以上三種演算法來解決,都需要分別做 \(n\)

次,來求解以每個點為起點的單源最短路,時間複雜度最慢分別是 \(O(nlogm),O(n^2m),O(n^2m)\),在稠密圖 \(m=n*(n-1)/2\)其中最快的都需要 \(O(n^3logm)\) ,最慢的甚至是 \(O(n^4)\) ,效率太低。因此,我們今天的主角 Floyd 就因解決多源最短路問題而誕生了!

2. Floyd 的思想和基本做法

Floyd演算法的基本思想是動態規劃。

\(dp_{ij}\) 表示 \(i\)\(j\) 的最短距離。(有 \(n\) 個點)

首先對於這個 \(dp\) 陣列的初始化就是將輸入的邊 \(x-y\) 權值為 \(z\) (無權圖就是 \(1\)

),如果圖是無向,則 \(dp_{xy}=dp_{yx}=z\) ,如果圖是有向,則 \(dp_{xy}=z\),最後將所有 \(dp_{ii}=0 (0\le i\le n)\),比較顯然,這裡不做解釋。

接著我們進行狀態轉移。顯然,我們要轉移 \(dp_{ij}\),就需要找一個點 \(k\),來進行轉移,也就是 \(dp_{ij}\gets min(dp_{ij},dp_{ik}+dp_{kj})\),其中 \(dp_{ik}+dp_{kj}\) 就表示 \(i-k\) 的最短路與 \(j-k\) 的最短路之和,其實也就相當於一個鬆弛操作。

這裡特別要注意的是:我們的 \(k\) 那一層迴圈一定要放在 \(i\)

\(j\) 兩層迴圈之外,因為如果放在 \(i,j\) 以內的話,你就會發現每兩個點的最短路只會被算到一次,而當你在進行狀態轉移時,你只算到一次的話,你會發現有些點在轉移時,還沒有被更新,就會出現沒有求出最短路的情況,所以,\(k\) 的迴圈要放到 \(i,j\) 的迴圈之外。

Floyd演算法由於 \(i,j,k\) 都要列舉一層迴圈,所以時間複雜度為 \(O(n^3)\),比開頭講的三個演算法要快。