目錄
- 0.最短路徑問題
0.1 最短路徑問題描述
?0.1.1 最短路徑的定義
?0.1.2 最短路徑問題的幾個變體
0.2 最短路徑性質
?0.2.1 最優子結構
?0.2.2 最短路徑的表示
?0.2.3 松弛操作
?0.2.4 最短路徑和松弛操作的性質 - 1.單源最短路徑
1.1 Bellman-Ford算法——針對每個結點進行|E|次松弛
1.1-1 SPFA算法——Bellman-Ford算法的改進
1.2 有向無環圖中的單源最短路徑問題——按拓撲排序進行松弛
1.3 非負權重有向無環圖中的單源最短路徑問題——Dijkstra算法(貪心)
1.4 (線性規劃)差分約束和最短路徑——(三角不等式)歸約到單源最短路徑問題 - 2.所有結點對的最短路徑問題
2.1 最短路徑和矩陣乘法
?2.1.1 最優子結構
?2.1.2 遞歸解
?2.1.3 自底向上計算最短路徑權重——Θ(n4)
?2.1.4 改進算法的運行時間——Θ(n3lgn)
2.2 Floyd-Warshall算法——Θ(V3)(或Θ(n3))
?2.2.1 最優子結構
?2.2.2 遞歸解
?2.2.3 自底向上計算最短路徑權重
?2.2.4 構建最短路徑
?2.2.5 有向圖的傳遞閉包
2.3 基本方法Θ(n4)與Floyd-Warshall方法Θ(n3)對比
?2.3.1 基本方法的核心(動態規劃)
?2.3.2 Floyd-Warshall方法的核心(動態規劃)
?2.3.3 兩種方法的對比
2.4 用于稀疏圖的Johnson算法
?2.4.1 重新賦予權重維持最短路徑(h是結點的函數,有點類似于攤還分析中的勢函數)
?2.4.2 通過重新賦值來生成非負權重——參考差分約束系統(三角不等式)
?2.4.3 Johnson算法
2.5 三種計算所有結點對的算法對比
0.最短路徑問題
0.1 最短路徑問題描述
0.1.1 最短路徑的定義
- 給定一個帶權重的有向圖G=(V, E)和權重函數w:E ->R,該權重函數將每條邊映射到實數值的權重上。
圖中一條路徑p=<v0, v1, ..., vk>的權重w(p)是構成該路徑的所有邊的權重之和:
定義從結點u到結點v的最短路徑權重δ(u, v)如下:
從結點u到結點v的最短路徑則定義為任何一條權重為w(p) = δ(u, v)的從u到v的路徑p。
0.1.2 最短路徑問題的幾個變體
- 單源最短路徑問題
給定一個圖G=(V, E),希望找到從給定源節點s∈V到每個結點v∈V的最短路徑。 - 單目的地最短路徑問題
找到從每個結點v到給定目的地結點t的最短路徑。如果將圖的每條邊的方向翻轉過來,可以將該問題轉換為單元最短路徑問題 - 單節點對最短路徑問題
找到從給定結點u到給定v的最短路徑。如果解決了針對單個結點u的單源最短路徑問題,那么也就解決了這個問題 - 所有結點對最短路徑問題
對于每對結點u和v,找到從結點u到結點v的最短路徑。
0.2 最短路徑性質
0.2.1 最優子結構
-
兩個結點之間的一條最短路徑包含著其他的最短路徑。
0.2.2 最短路徑的表示
- 最短路徑不能包含權重為負值的環路。
- 最短路徑也不能包含權重為正值的環路,因為只要將環路從路徑上刪除就可以得到一條源結點和終結點與原來路徑相同的一條權重更小的路徑。
- 最短路徑也不包含權重為0的環路,總是可以去掉。
(針對單源最短路徑問題)不失一般性,假定在找到的最短路徑中沒有環路,即它們都是簡單路徑。由于圖G=(V, E)中的任意無環路徑最多包含|V|個不同的結點,它也最多包含|V| - 1條邊。
- 前驅子圖Gπ = (Vπ, Eπ)
Vπ = {v ∈ V: v.π ≠ NIL} ∪ {s}
Eπ = {(v.π, v) ∈ E: v∈Vπ - {s}}
在單源最短路徑算法終止時,Gπ是一棵最短路徑樹。 -
最短路徑樹:是一棵有根結點樹,該樹包括了從源節點s到每個可以從s到達的結點的一條最短路徑。
一棵根節點為s的最短路徑樹是一個有向子圖G' = (V', E'),這里V'屬于V,E'屬于E:
1)V'是圖G中從源節點s可以到達的所有結點的集合
2)G'形成一棵根節點為s的樹
3)對于所有的結點v∈V',圖G'中從結點s到結點v的唯一簡單路徑是圖G中從結點s到結點v的一條最短路徑。
最短路徑不一定是唯一的,最短路徑樹也不一定是唯一的
0.2.3 松弛操作
- v.d:記錄從源節點s到結點v的最短路徑權重的上界。v.d為s到v的最短路徑估計。
- 松弛操作是唯一導致最短路徑估計和前驅結點發生變化的操作。
- Dijkstra算法對每條邊僅松弛一次;Bellman-Ford算法對每條邊松弛|V| - 1次
0.2.4 最短路徑和松弛操作的性質
1)三角不等式性質——最短路徑的定義
2)上界性質
3)非路徑性質
4)收斂性質——最優子結構
5)路徑松弛性質
6)前驅子圖性質
- 24.16本質上說明兩點:
1)Gπ是一個有向無環圖
2)對于每個結點v ∈Vπ,在圖Gπ中存在一條從源節點s到結點v的唯一簡單路徑。
這里有一個說明:前驅結點賦值只在松弛操作的時候進行,一旦松弛操作發生,就表明源結點s到該結點v的和v.π的距離為有限值。s不可達的結點u當且僅當u.d = ∞。
歸納法:
初始時,開始時s從s可達,第一次運行之后,加入Vπ的結點是v.π = s的結點。也即v.π和v都屬于Vπ,且v和v.π都可達
歸納步,假設v和v.π屬于Vπ,v.π可達。因為(v.π, v)屬于Eπ,則v可達,所以存在一條簡單路徑到v。
- 證明需要證明三點:
一棵根節點為s的最短路徑樹是一個有向子圖G' = (V', E'),這里V'屬于V,E'屬于E:
1)V'是圖G中從源節點s可以到達的所有結點的集合
2)G'形成一棵根節點為s的樹
3)對于所有的結點v∈V',圖G'中從結點s到結點v的唯一簡單路徑是圖G中從結點s到結點v的一條最短路徑。 - 24.17說明:
1)v.π≠NIL,則為從s可達
2)Gπ中的簡單路徑,說明經過了松弛了操作,即在操作前,一定有vi.d ≥ vi-1.d + w(vi-1, vi),否則不會成為前驅結點。
1.單源最短路徑
1.1 Bellman-Ford算法——針對每個結點進行|E|次松弛
1)算法描述
- 該算法解決的是一般情況下的單元最短路徑問題。邊的權重可以為負值。
- 該算法返回一個布爾值,表明是否存在一個從源節點可以到達的權重為負值的環路。如果沒有這種環路存在,算法將給出最短路徑和它們的權重。
- 算法對圖的每條邊進行|V| - 1次處理。
- Bell-Ford算法的總運行時間為O(VE)
2)算法正確性證明
- 引理24.2關鍵是路徑松弛性質
推論24.3關鍵是非路徑性質
- 定理24.4關鍵是三角不等式、前驅子圖性質
1.1-1 SPFA算法——Bellman-Ford算法的改進
1)算法描述
- 建立一個先進先出的隊列用來保存待優化的結點,優化時每次取出隊首結點u,并且用u點當前的最短路徑估計值對離開u點所指向的結點v進行松弛操作,如果v點的最短路徑估計值有所調整,且v點不在當前的隊列中,就將v點放入隊尾。這樣不斷從隊列中取出結點來進行松弛操作,直至隊列空為止。
- (參考prim最小生成樹算法)關于SEARCH(Q, v),可以附加一個標志位來輔助,如果加入隊列,則將結點的標志位置1,出對置0.初始化為0,這樣可以在O(1)內對v是否屬于隊列Q進行判斷。
2)算法正確性證明
- SPFA算法也是使用了松弛操作,松弛操作只會讓路徑距離越來越小
- SPFA將一個結點v松弛之后,如果v不在隊列中,則將v加入隊列。這是一個很直觀的操作:結點v的距離減小了,那么從結點v發出的所有臨近結點距離都可能減小,所以要一一檢查。SPFA這樣將距離更改的影響一層一層往下擴散,直至所有距離都是最小為止。
- 那么最短路徑不存在呢?如果存在負權圈,并且起點可以通過一些頂點到達負權圈,那么利用SPFA算法會進入一個死循環,因為d值會越來越小,并且沒有下限,使得最短路不存在。那么我們假設不存在負權圈,則任何最短路上的點必定小于等于|V|個(沒有圈),換言之,用一個數組c[i]來記錄i這個點入隊的次數,所有的c[i]必定都小于等于n,所以一旦有一個c[i] > |V|,則表明這個圖中存在負權圈。
證明循環不變式:每次while循環前,所有可能引起松弛的點都在隊列中
- 初始化:隊列中只有s,s.d + w(s, v) < v.d = ∞,其他點不滿足這個條件,只有s會引起松弛操作
-
保持:假設i次while循環之前,所有可能引起松弛的點都在隊列中,那么i次while循環之后,去掉了u,將引起了松弛操作的所有v加入到隊列中。
考慮v.d > u.d + w(u, v)的情況下x.d > v.d + w(x, d):
1)如果是循環之前已經成立,則v已經在隊列中
2)如果是循環后的成立,那么要么是x.d增大(不可能)或者v.d減小,如果v.d減小,則要將v加入到隊列中。
無論哪種情況都滿足情況。 - 終止:隊列為空,則所有的頂點都不能松弛了,都到了最小。
3)SPFA算法改進——貪心策略(迅速降低結點的路徑,收斂更快)
- SLF:Small Label First 策略,設要加入的節點是j,隊首元素為i,若dist(j)<dist(i),則將j插入隊首,否則插入隊尾;
- LLL:Large Label Last 策略,設隊首元素為i,隊列中所有dist值的平均值為x,若dist(i)>x則將i插入到隊尾,查找下一元素,直到找到某一i使得dist(i)<=x,則將i出隊進行松弛操作。
- SLF 可使速度提高 15 ~ 20%;SLF + LLL 可提高約 50%。
1.2 有向無環圖中的單源最短路徑問題——按拓撲排序進行松弛
1)算法描述
- 可以有權重為負值的邊。
- 根據結點的拓撲排序來對帶權重的有向無環圖G=(V, E)進行邊的松弛的操作,便可以在Θ(V + E)時間內計算出從單個源節點到所有結點之間的最短路徑。
拓撲排序:有向無環圖包含從結點u到結點v的一條路徑,則u在拓撲排序的次序中位于v的前面。
- DAG——Directed Acyclic Graph有向無環圖
- 運行時間:
1)拓撲排序時間為Θ(V + E)
2)初始化時花費Θ(V),松弛次數為Θ(E)
因此總時間為Θ(V + E)
2)算法正確性證明
- 關鍵在路徑松弛性質
3)PERT圖中的關鍵路徑
- PERT——Program Evaluation and Review Technique。計劃評審技術,簡單地說,PERT是利用網絡分析制定計劃以及對計劃予以評價的技術。它能協調整個計劃的各道工序,合理安排人力、物力、時間、資金,加速計劃的完成。在現代計劃的編制和分析手段上,PERT被廣泛地使用,是現代項目管理的重要手段和方法。
- PERT圖是一個有向無環圖,在圖中,每條邊代表需要進行的工作,邊上的權重代表執行該工作所需的時間。
如果邊(u, v)進入結點v,邊(v, x)離開結點v,則工作(u, v)必須在工作(v, x)前完成。
PERT圖中的一個路徑代表的是一個工作執行序列。 - 關鍵路徑是該有向無環圖中一條最長的路徑,該條路徑代表執行任何工作序列所需要的最長時間。
因此,關鍵路徑上的權重提供的是執行所有工作所需時間的下界 - 兩種方法找到PERT圖中的關鍵路徑:
1)將所有權重變為負數,然后運行DAG-SHORTEST-PATHS
2)運行DAG-SHORTEST-PATHS,但進行如下修改:在INITIALIZE-SINGLE-SOURCE的第二行將正無窮改為負無窮,在RELAX過程中將>變為<
這里求的是源點s到各點的最長距離路徑(這里默認PERT圖所有權重都為正值),因此,要符號要變向,直觀上是方法2);
當將所有權重變為負之后,求最小,即為求最大。
1.3 非負權重有向無環圖中的單源最短路徑問題——Dijkstra算法
1)算法描述——廣度優先搜索
- 要求所有邊的權重為非負值。
- 算法維持集合S,從源節點s到該集合中每個結點之間的最短路徑已經被找到。
算法重復從結點集V-S中選擇最短路徑估計最小的結點u,將u加入到集合S,然后對所有從u發出的邊進行松弛。
-
算法運行時間分析
三種優先隊列操作:
1)第3行的INSERT操作——|V|
2)第5行的EXTRACT-MIN——|V|
3)第8行的DECREASE-MIN——|E|(聚合分析)
數組(1-|V|編號來維持)——O(V2 + E),INSERT和DECREASE-KEY操作的時間為O(1),EXTRACT-MIN操作時間為O(V);
二叉堆——O((V+E)lgV);
斐波那契堆——O(VlgV+E);
2)算法正確性證明
- 理解的關鍵點有:收斂性質得到y.d = δ(s, y)
-
Dijkstra算法的貪心選擇性質:
1)加入集合S的,都有u.d = δ(s, u);此時與S中點相鄰的點v都已經被松弛過了。并且s到最小的v必然存在一條最短路徑,并且已經被松弛過了,因此v.d=δ(s, v)肯定成立。
2)為什么s到最小的v存在一條最短路徑,而且必然是s~u-v,因為所有的路徑是非負的,并且v還未加入到S中,所以任何經過其他路徑再到v的路徑都要比這條路徑長。
1.4 (線性規劃)差分約束和最短路徑——(三角不等式)歸約到單源最短路徑問題
1.4.1 線性規劃
- 單源單目的地最短路徑問題和最大流問題都是線性規劃問題的特例。存在著更快的算法。
1.4.2 差分約束系統——判斷是否存在可行解
1)差分約束系統
等價于:
- 差分約束系統在許多不同的應用里都會出現。
xi可能代表事件發生的時間。每個約束條件給出的是在兩個事件之間必須間隔的最短時間或最長時間。
2)約束圖——從圖論的觀點來理解差分約束系統
- 在Ax ≤ b的差分約束系統中,將m x n的線性規劃矩陣A看作是一張由n個結點和m條邊構成的圖的鄰接矩陣的轉置。
a.每個結點vi(其中i=1,2,...,n)對應n個未知變量xi中的一個
b.每條有向邊對于m個不等式中的一個,如果xj - xi ≤ bk是一個差分約束條件,則邊(vi, vj)的權重為bk。
上圖對應的約束圖為:
- 關鍵在于三角不等式
3)求解差分約束系統——Bellman-Ford算法
- 現在的算法是n+1個結點和n+m條邊,因此運行時間為O((n+1)(n+m))
-
可以修改算法,使其能夠在O(nm)時間內完成運算,即使m遠遠小于n。
4)求解差分約束系統——Bellman-Ford算法的改進
- 差分約束系統轉換為的約束圖有三個特點:
1)如果首先按照邊{(0,1) (0,2) (0,3) (0,4) (0,5)}進行松弛,則vi.d(其中1≤ i ≤5)均為0
2)因為v0只有出邊,所以v0.d一直不變,一直為0
3)因此后面每次按照邊{(0,1) (0,2) (0,3) (0,4) (0,5)}進行松弛時,vi.d(其中1≤ i ≤5)的值都不會變化
因為,松弛只會減小vi.d(其中1≤ i ≤5)的值,而第一次松弛已經就變為0
- 因此,根據上述特點,有如下的修改:
一個可行的方案是,將每個結點賦初值0,從而省略掉初始源點。因為初始源點只有出邊,沒有入邊,所以迭代過程不會影響初始源點以及初始源點到任一點的路徑權值。這樣可以將邊的數量降為m,結點數量降為n,總時間為O(n*m)。
2.所有結點對的最短路徑問題
- 可以運行|V|次單源最短路徑算法,來解決所有結點對之間的最短路徑問題。
- 使用鄰接矩陣表示圖。權重矩陣W=(wij)
- 最短路徑輸出表示為矩陣D = (dij),其中dij代表的是從結點i到結點j的一條最短路徑的權重。
- 還需要計算前驅結點矩陣Π = (πij),其中πij在i = j或從i到j不存在路徑時為NIL,在其他情況下給出的是從結點i到結點j的某條最短路徑上結點j的前驅結點。
對于每個結點i ∈V,定義圖G對于結點i的前驅子圖為Gπ,i = (Vπ,i, Eπ,i),其中:
Vπ,i = {j ∈V: πij ≠ NIL}∪{i}
Eπ,i = {(πij, j): j ∈Vπ,i - {i}}
如果Gπ,i是一棵最短路徑樹,則下面的過程將打印出從結點i到結點j的一條最短路徑。
2.1 最短路徑和矩陣乘法
2.1.1 最優子結構
- 一條最短路徑的所有子路徑都是最短路徑。(假定沒有負值的環路)
2.1.2 遞歸解
-
設lij(m)為從結點i到結點j的至多包含m條邊的任意路徑中的最小權重。
1)當m=0
2)當m≥1
因為對于j有wjj=0,所以后面的等式成立。 -
沒有負值環路,由于該路徑是簡單路徑,其包含的邊最多是n-1條。從結點i到結點j的由多于n-1條邊構成的路徑(含有正值環路)不可能比從i到j的最短路徑權重更小的權重。
2.1.3 自底向上計算最短路徑權重——Θ(n4)
- 遞歸計算出矩陣序列L(1), L(2),..., L(n-1)。有L(m) = (lij(m))。
最后的矩陣L(n-1)包含的是最短路徑的實際權重。
并且有L(1) = W。
2.1.4 改進算法的運行時間——Θ(n3lgn)
1)矩陣乘法與EXTEND-SHORTEST-PATHS的對比
2)利用矩陣乘法的思想改進算法
關鍵點1.目標不是要計算所有的L(m),感興趣的僅僅是L(n-1)。
-
關鍵點2.對于所有的m ≥ n-1,有L(m) = L(n-1)。
-
關鍵點3.為什么這樣算也是可以的?
因為EXTEND-SHORTEST-PATHS過程定義的乘法滿足結合律。
矩陣乘法結合律
EXTEND-SHORTEST-PATHS過程只要將矩陣乘法中的+改為min,乘法改為+即可:
EXTEND-SHORTEST-PATHS結合律
2.2 Floyd-Warshall算法——Θ(V3)(或Θ(n3))
- 不能存在負值環路
2.2.1 最優子結構
- Floyd-Warshall算法考慮的是一條最短路徑上的中間結點,簡單路徑p = <v1, v2,..., vk>的中間結點指的是除v1,vk之外的任意結點。
- 假設G的所有結點為V={1, 2, ..., n},考慮其中的一個子集{1, 2, ..., k},k是某個小于n的整數。
對于任意結點對i,j,考慮從結點i到結點j的所有結點均取自集合{1, 2, ..., k}的路徑,設p為其中權重最小的路徑(p是簡單路徑)。
1)如果k不是路徑p的中間結點,則路徑p上的所有中間結點都屬于集合{1, 2, ..., k-1};
2)如果k是路徑p的中間結點,將p分解為(i ~ k)p1和(k~j)p2。因此p1和p2的中間結點均是取自集合{1, 2, ..., k-1}的一條最短路徑。
2.2.2 遞歸解
- 設dij(k)表示從結點i到結點j的所有中間結點全部取自集合{1, 2, ..., k}的一條最短路徑的權重。
對于任何路徑來說,所有的中間結點都屬于集合{1, 2, ..., n},矩陣D(n) = (dij(n))給出最后的答案。
2.2.3 自底向上計算最短路徑權重
-
該算法的空間可以降低到Θ(n2)
-
有一種解釋dik(k) = dik(k-1),因為兩個端點為i和k,那么中間的點肯定不包括k,否則包括兩個k點,形成環路,必然是負值環路。
算法運行時間為Θ(n3)
-
證明dij(k)計算的最短路徑上沒有環路(環路都是非負值)
這個證明也等同于證明i-k和k-j上的最短路徑不可能經過相同的點,作為Floyd-Warshall算法正確性證據之一。
2.2.4 構建最短路徑
1)方法1
- 先計算出最短路徑權重矩陣D,然后從D矩陣來構造前驅矩陣Π,該方法的運行時間可限制在O(n3)。
2)方法2
-
可以在計算矩陣D(k)的同時計算前驅矩陣Π(k)。
Π = Π(n);
πij(k)為從結點i到結點j的一條所有中間結點都取自集合{1, 2, ..., k}的最短路徑上j的前驅結點。
1)k = 0
從i到j的一條最短路徑沒有中間結點,因此
2)k ≥ 1, k ≠ j
-
證明:對于所有的結點i ∈V,前驅子圖Gπ,i是一棵根節點為i的最短路徑樹。
也即證明矩陣π的第i行所誘導的子圖應當是一棵根節點為i的最短路徑樹。
(本質)也即證明從任何結點出發的到其他所有結點的最短路徑構成一棵最短路徑樹。
1)前驅子圖的定義
πij在i = j或從i到j不存在路徑時為NIL,在其他情況下給出的是從結點i到結點j的某條最短路徑上結點j的前驅結點。
πij(k)為從結點i到結點j的一條所有中間結點都取自集合{1, 2, ..., k}的最短路徑上j的前驅結點。
對于每個結點i ∈V,定義圖G對于結點i的前驅子圖為Gπ,i = (Vπ,i, Eπ,i),其中:
Vπ,i = {j ∈V: πij ≠ NIL}∪{i}
Eπ,i = {(πij, j): j ∈Vπ,i - {i}}
如果Gπ,i是一棵最短路徑樹,則下面的過程將打印出從結點i到結點j的一條最短路徑。
2)證明關鍵點
πij(k) = l,意味著dij(k) > il(k) + wlj。(嚴格對于時,l ≠ j)因為確定為前驅時,一定意味著dij變小了,在調整之前,則肯定是大于。
因此借助于定理24.16可以證明是正確的。
這里有一個說明:前驅結點賦值只在松弛操作的時候進行,一旦松弛操作發生,就表明源結點s到該結點v的和v.π的距離為有限值。s不可達的結點u當且僅當u.d = ∞。
歸納法:
初始時,開始時s從s可達,第一次運行之后,加入Vπ的結點是v.π = s的結點。也即v.π和v都屬于Vπ,且v和v.π都可達
歸納步,假設v和v.π屬于Vπ,v.π可達。因為(v.π, v)屬于Eπ,則v可達,所以存在一條簡單路徑到v。
2.2.5 有向圖的傳遞閉包
- 傳遞閉包
給定有向圖G=(V, E),結點集合為V={1, 2, ..., n},判斷對于所有的結點i和j,圖G是否包含一條從結點i到結點j的路徑,定義圖G的傳遞閉包為圖G* = (V, E*)
E* = {(i, j):如果圖G中包含一條從結點i到j的路徑} - 方法1——Floyd-Warshall算法——Θ(n3)
給E中每條邊賦予權重1,然后運行Floyd-Warshall算法。如果存在一條從i到j的路徑,則有dij < n;否則,dij = ∞。 - 方法2——Θ(n3)
用邏輯或和邏輯與操作替換Floyd-Warshall算法中的算術操作min和+。
對于i, j, k ∈ {1, 2, ..., n},定義:如果G中存在一條從結點i到結點j的,且所有中間結點都取自集合 {1, 2, ..., k}的路徑,則tij(k)為1,否則為0。
構建G* = (V, E*)的方法為:將邊(i, j)置于集合E*中當且僅當tij(n)為1。
1)如果k = 0,
2)如果k ≥ 1,
2.3 基本方法Θ(n4)與Floyd-Warshall方法Θ(n3)對比
2.3.1 基本方法的核心
- 設lij(m)為從結點i到結點j的至多包含m條邊的任意路徑中的最小權重。
1)當m=0
2)當m≥1,因為對于j有wjj=0,所以后面的等式成立。
- 遞歸計算出矩陣序列L(1), L(2),..., L(n-1)。有L(m) = (lij(m))。
最后的矩陣L(n-1)包含的是最短路徑的實際權重。
并且有L(1) = W。
2.3.2 Floyd-Warshall方法的核心
-
假設G的所有結點為V={1, 2, ..., n},考慮其中的一個子集{1, 2, ..., k},k是某個小于n的整數。
對于任意結點對i,j,考慮從結點i到結點j的所有結點均取自集合{1, 2, ..., k}的路徑,設p為其中權重最小的路徑(p是簡單路徑)。
1)如果k不是路徑p的中間結點,則路徑p上的所有中間結點都屬于集合{1, 2, ..., k-1};
2)如果k是路徑p的中間結點,將p分解為(i ~ k)p1和(k~j)p2。因此p1和p2的中間結點均是取自集合{1, 2, ..., k-1}的一條最短路徑。
-
設dij(k)表示從結點i到結點j的所有中間結點全部取自集合{1, 2, ..., k}的一條最短路徑的權重。
對于任何路徑來說,所有的中間結點都屬于集合{1, 2, ..., n},矩陣D(n) = (dij(n))給出最后的答案。
- 該算法的空間可以降低到Θ(n2)
2.3.3 兩種方法的對比
- 基本方法是將dij分解為dik和一條邊(k, j),當然dik的邊數減一。
因此,計算的時候,要針對k的所有可能性進行遍歷。 - Floyd-Warshall的方法是將dij分解為兩段,dik和dkj
-
Floyd-Warshall相對于基本方法,是怎樣去掉大量冗余計算的,這種思路是怎樣得來的?
Floyd-Warshall利用的是去掉特定的點,比如頂點集合{1, 2, ..., k},逐漸去掉點k, k-1, ..., 1。
這跟去掉一個邊不同(去掉與j相連的邊),因為你不知道去掉的是哪個邊,所以要遍歷與j相連的所有頂點(k->j),找出最小的,確定去掉的是哪個邊。
這里最大的不同是:Floyd-Warshall去掉中間一個確定的點,不用遍歷求最小;基本方法去掉一個不確定的邊,需要遍歷找到是哪個邊
2.4 用于稀疏圖的Johnson算法
Johnson可以在O(V2lgV+VE)時間內找到所有結點對之間的最短距離。
對于稀疏圖,Johnson算法的漸近表現要優于重復平方法和Floyd-Warshall算法。Johnson可以報告包含一個權重為負值的環路。
Johnson算法使用Dijkstra算法和Bellman-Ford算法作為子程序。Johnson算法的核心技術是重新賦予權重。
1)如果G=(V, E)中所有的權重w為非負值,可以通過對每個結點運行一次Dijkstra來找到所有結點對之間的最短路徑。如果使用斐波那契堆最小優先隊列,該算法的運行時間為O(V2lgV+VE)。
2)如果G包含權重為負值的邊,但沒有負值的環路,那么只要計算出一組新的非負權重值,然后使用1)中的方法。
3)對于有負值環路的,報告存在負值環路。新賦予的權重w'必須滿足兩個重要性質:
1)(重新賦予權重維持最短路徑)對于所有結點對u, v ∈V,一條路徑p是在使用權重函數w時從u到v的一條最短路徑,當且僅當p是使用權重函數w'時從u到v的一條最短路徑。
2)(權重為非負值)對于所有的邊(u, v),新權重w'(u, v)為非負值。
2.4.1 重新賦予權重維持最短路徑(h是結點的函數,有點類似于攤還分析中的勢函數)
-
關鍵是將h定義為結點的函數,類似于勢函數,這樣路徑上中間可以進行裂項抵消。
2.4.2 通過重新賦值來生成非負權重——參考差分約束系統(三角不等式)
對于原圖G=(V, E)制作一個對應的新圖。
新圖G' = (V', E'),其中:
V' = V ∪ {s},s是一個新結點s ? V;
E' = E ∪ {(s, v): v ∈ V};w權重函數進行擴展
1)對于所有的結點v ∈ V, w(s, v) = 0。
結點s沒有進入的邊,除了以s為源節點的最短路徑外,圖G'中沒有其他包含結點s的最短路徑。且G'不包含權重為負值的環路當且僅當圖G不包含權重為負值的環路。
2)假設G和G'都不包含權重為負值的環路
對于所有的結點v ∈ V',h(v) = δ(s, v)。
根據三角不等式,對于所有的邊(u, v) ∈ E',有h(v) ≤ h(u) + w(u, v).
因此定義w'(u, v) = w(u, v) + h(u) - h(v) ≥ 0.
因此所有的邊都是非負的。
2.4.3 Johnson算法
2.5 三種計算所有結點對的算法對比
基本方法和重復平方法——Θ(n4)和Θ(n3lgn)
1)動態規劃
2)基本方法去掉一個不確定的邊,需要遍歷找到是哪個邊
3)重復平方法與基本方法的區別在于:基本方法到最終解,每次增加一條邊;重復平方法每次增加一倍。Floyd-Warshall——Θ(n3)
1)動態規劃
2)Floyd-Warshall去掉中間一個確定的點,不用遍歷求最小Johnson算法——O(V2lgV+VE)(稀疏圖特別適合)
1)基于Bellman-Ford判斷是否有負值環路
2)最大的特色是基于單源最短路徑算法來進行,對每一點分別利用Dijkstra算法(時間效率最好的單源最短路徑算法)
2)Dijkstra算法有限值,就利用“差分約束系統”里面的方法,利用三角不等式,將w'(u, v)變成非負的