算法導論 - 第25章 每對頂點間的最短路徑

每對頂點間的最短路徑的算法有三種,每一種都可以檢測圖是否存在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).

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章