每對頂點間的最短路徑的演算法有三種,每一種都可以檢測圖是否存在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;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(m)(i,j)=min
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).
演算法導論 第25章 所有結點對的最短路徑問題
前面講了單源最短路徑問題,指定乙個原點乙個終點,找到最短路徑。但是如果我們要求所有結點對呢?方案一 可以對每乙個結點呼叫一次單源最短路徑演算法,一共呼叫 v 次。每指定乙個原點,可以求出其他任何點到該原點的舉例 對於權值為非負的圖,可以呼叫dijkstra演算法,不同的優先佇列實現得到不同的時間複雜...
《演算法導論》筆記 第3章 函式的增長
第3章 函式的增長 漸進記號 記號對任乙個函式f n 若存在正常數c1,c2,使當n充分大時,f n 能被夾在c1g n 和c2g n 中間,則f n 屬於集合 g n 因為 g n 是乙個集合,可以寫成 f n g n 表示f n 是 g n 的元素。g n 的定義需要每個成員f n g n 都是...
資料結構的擴張 演算法導論第14章(194)
偽 解釋 為明白os select是如何操作的,在上圖所示的順序統計圖上查詢第17小元素的查詢過程。以x為根開始,其關鍵字為26。i 17.因為在26的左子樹大小為12,故他的秩為13,因此,秩為17的節點是26的右子樹第17 13 4小得瑟元素。遞迴呼叫後,x為關鍵字41的節點,i 4,因為41的...