每對頂點間的最短路徑的算法有三種,每一種都可以檢測圖是否存在weighg小於0的cycle。
前兩種算法用了動態規劃的方法,最後一種算法對每個定點計算單源最短路徑。
與求單源最短路徑的算法不同,求每對頂點間的最短路徑的算法採用網的矩陣表示法(除了最後一種算法,最後一種算法採用圖的鄰接表表示法)。用矩陣W表示一個網,其中矩陣的元素W(i,j)表示頂點i到頂點j的edge的weight。如果頂點i到頂點j之間沒有edge,則W(i,j)等於無窮大。W(i,i)等於0。
用n表示圖中頂點的個數。
算法1:
用矩陣L(m)來表示每對頂點間的最短路徑的weight,每對頂點之間的最短路徑最多隻有m條edge。
L(1)=W
L(m)(i,j) = min{L(m-1)(i,k) + W(k,j)};k=[1,n]
由於最短路徑的長度(指edge的個數,不是隻路徑的weight)必然小於等於n-1,所以L(n-1)就是我們所需要求的。
L(1) ---> L(2) ---> L(3) ---> L(4) ---> ... ---> L(n-1)
該方法的時間複雜度爲O(n^4)。
計算過程中,如果某個矩陣的對角線元素小於0,(對角線元素只能等於0或小於0),說明網中存在weight小於0的cycle。
算法2:
算法2的名字叫Floyd-Warshall Algorithm。該方法也是採用動態規劃的方法。思路與算法1差不多。
用矩陣D(m)來表示每對頂點間的最短路徑的weight,每對頂點之間的最短路徑的中間結點(也就是最短路徑中去掉source和destination後剩下的所有頂點)的編號最大爲m。
D(0)=W (表示沒有中間結點)
D(1)(i,j)=min{D(0)(i,1)+D(0)(1,j)}
D(m)(i,j)=min{D(m-1)(i,m)+D(m-1)(m,j)}
D(n)就是我們需要求的。
D(0) ---> D(1) ---> D(2) ---> D(3) ---> D(n)
算法複雜度爲O(n^3)
計算過程中,如果某個矩陣的對角線元素小於0,(對角線元素只能等於0或小於0),說明網中存在weight小於0的cycle。
算法3:
算法3的名字叫Johnson's algorithm。該算法對每個頂點計算單源最短路徑。單源最短路徑的算法包括Bellman-Ford算法和Dijkstra算法。
如果對每個頂點採用Bellman-Ford算法,那就沒什麼事情。Bellman-Ford算法本身可以檢測是否存在weight小於0的cycle。但Bellman-Ford的時間複雜度比Dijkstra算法沒有優勢,因此Johnson's algorithm是對每個頂點採用Dijkstra算法。由於Dijkstra算法的要求是網中不能存在weight小於0的edge。因此需要採取一些辦法來解決這個問題。
Johnson's algorithm通過對每條edge重新賦予weight來保證每條edge的weight大於等於0。用W(u,v)表示頂點u到頂點v的weight,如果edge(u,v)不存在,則W(u,v)爲無窮大。用W’(u,v)來表示新的weight。用D(i,j)來表示原來weight條件下,頂點i到頂點j之間的最短路徑的weight,用D'(i,j)表示用W‘時,頂點i到頂點j之間最短路徑的weight。G=(V,E,W), G' = (V,E,W')。
則顯然,我們特地生成出個G’,肯定是要滿足一定條件的。這些條件就是:
1 在G中,設p爲頂點i到頂點j之間的最短路徑,則p也必須是在G’中,頂點i到頂點j之間的最短路徑。反之亦然。
2 顯然,W‘(i,j)必須都大於等於0。
那麼怎麼生成W',使得G’滿足以上兩個條件呢?
假設對每個頂點映射一個值,用函數h來表示,即h(u)是某個數,u是圖G中的任何一個頂點。
讓W'(i,j) = W(i,j)+h(i)-h(j)
則不管h這個映射如何實現,用該方法產生的G‘滿足條件1。
設p(i,j)是G中任何一對頂點的任一條路徑的weight,p'(i,j)是該路徑在G’中的weight。則有關係:p'(i,j) = p(i,j)+h(i)-h(j)
那如何構造h,使得G'滿足條件2?
在G’中增加一個頂點s,增加n條edge:(s,v1),(s,v2)....(s,vn)。每條邊的weight爲0。
我們看看新構造的G‘。由於頂點s沒有入邊,所以v1,v2,v3...vn之間的任何最短路徑都不會經過s。所以v1,v2,v3...vn中每對頂點的最短路徑,最短路徑的weight都保持不變。
以頂點s作爲source,用Bellman-Ford算法求單源最短路徑。求得d1,d2,d3...dn。顯然,di必然小於等於0。
我們採用映射h(u)=du來計算W’,就可以使得G‘滿足條件2。
證明:對edge(v,u),有du <= dv+W(v,u)。也就是h(u) <= h(v)+W(v,u),把v換成i,把u換成j,就是h(j) <= h(i)+W(i,j),即h(i)-h(j)>=-W(i,j)。
W'(i,j) = W(i,j)+h(i)-h(j)>=W(i,j) + (-W(i,j)) = 0。
Done!!
Johnson's algorithm僞代碼如下所示:
1 構造G’
2 以頂點s爲source,用Bellman-Ford算法求單源最短路徑。如果存在weight小於0的cycle,返回。
3 計算W'(i,j) = W(i,j)+h(i)-h(j)。
4 對G‘中每個頂點(s除外)調用Dijkstra方法,每對頂點的最短路徑的weight保存在矩陣D'(i,j)中。
5 D(i,j) = D'(i,j)+h(j)-h(i).