k Shortest Path
程度★★ 難度★★
k Shortest Walk
給定起點與終點,排名第k短的途徑。有可能跟最短途徑一樣長。或許可以翻譯為「第k短途徑」。
可以直接套用先前所學的Dijkstra's Algorithm,把DP表格開大一點,每個點都儲存前k短的長度,就能解決問題。時間複雜度為O(K * (E+VlogV))。
UVa 10740
k Shortest Path與k Shortest Trail
「第k短路徑」、「第k短跡」尚無有效率的演算法,大多是使用窮舉法,窮舉所有可能的路徑。時間複雜度本是指數時間,但如果配合了heuristic function,理想狀態之下,時間複雜度得宣稱是多項式時間。
主要的演算法有Yen's Algorithm與MPS Algorithm兩個。
http://imlazy.ycool.com/post.1956603.html
http://code.google.com/p/k-shortest-paths/
http://www.mat.uc.pt/~eqvm/OPP/KSPP/KSPP.html
http://blog.csdn.net/sharpdew/archive/2005/08/05/446510.aspx
ICPC 3624
Next-to-Shortest Path
程度★★★ 難度★★★
Strictly Second Shortest Walk
給定起點與終點,「嚴格次短途徑」是權重不等於最短途徑、權重盡量小的途徑。可能有許多條。
【註:以下假設有向圖上沒有負環、無向圖上沒有負邊,此時最短途徑恰等於最短路徑。至於有向圖上有負環、無向圖上有負邊的嚴格次短途徑,至今仍無人討論過。】
既然不想走這條路,就必須改走別條路。這是人之常情。
不想找到一條最短路徑,而想找到一條嚴格次短途徑,一種方式是觀察最短路徑的替代道路。
列出所有最短路徑,也就是「最短路徑圖」,從中尋找替代道路。由於替代道路太長,不利分析,於是發揮Incremental Method化整為零的精神:不觀察替代道路的所有邊,改為觀察替代道路上的一條邊。此精神先前也於Label Correcting Algorithm出現過。
【註:一張圖上,給定起點與終點,描出所有最短路徑,此處暫且稱之「最短路徑圖」。此概念尚未出現專有名詞。圖上只有正邊時,最短路徑圖是一張有向無環圖DAG;圖上有零邊或負邊,但是無負環時,最短路徑圖可能會額外出現零環。】
在有向圖上,替代邊必然是最短路徑以外的邊;在無向圖上,替代邊不僅可以採用最短路徑以外的邊,也可以逆行最短路徑上面的邊。替代邊設定為有向邊是比較完善的。
也就是說,嚴格次短途徑一定經過「最短路徑圖」以外的邊;若在無向圖上,也可以經過「最短路徑圖」上的反方向邊。
嚴格次短途徑仍是越短越好。當有一條途徑經過替代邊ij,要使此途徑盡量短,唯一的方法就是:從起點到i必須是最短路徑,從j到終點也必須是最短路徑。接著只要使用窮舉法,窮舉所有可能的替代邊,即可找到其中一條嚴格次短途徑。
一、預先計算起點s出發的單源最短路徑。 二、預先計算抵達終點t的單源最短路徑。 三、窮舉圖上每一條邊ij作為替代邊(無向圖則視作雙向都有邊): 甲、取得s->i的最短路徑。 乙、取得j->t的最短路徑。 丙、串成一條途徑s->i->j->t。 子、若s->i->j->t是最短路徑,表示邊ij不是替代邊,則捨棄之。 丑、若s->i->j->t不是最短路徑,就有可能是嚴格次短途徑,則紀錄之。 四、於丑,當中最短的途徑,便是嚴格次短途徑。
窮舉所有邊的過程,其時間複雜度為O(E),必然小於單源最短路徑的時間複雜度。因此可以直接宣稱時間複雜度等同求單源最短路徑的時間複雜度。
UVa 10342
Next-to-Shortest Path(Strictly Second Shortest Path)
給定起點與終點,「嚴格次短路徑」是權重不等於最短路徑、權重盡量小的路徑。
有向圖 正零負權重 NP-Complete 光是最短路徑就已經是 NP-complete 正零權重 NP-Complete 1997 美國 正權重 ? open problem 無向圖 正零負權重 NP-Complete 光是最短路徑就已經是 NP-complete 正零權重 P O(V^6) 2011 日本 正權重 P O(最短路徑) 2010 台灣
正權重無向圖的演算法,時間複雜度宣稱是O(E+VlogV)。
建立「最短路徑圖」,採用Divide and Conquer,將嚴格次短路徑分為「經過最短路徑圖以外的邊」與「經過最短路徑圖的反方向邊」兩種。這兩種情形分別被以下兩篇論文解決:
Kuo-Hua Kao, Jou-Ming Chang, Yue-Li Wang, Justie Su-Tzu Juan. A Quadratic Algorithm for Finding Next-to-Shortest Paths in Graphs. Algorithmica, 2010.
Bang-Ye Wu. A Simpler and More Efficient Algorithm for the Next-to-Shortest Path Problem. Combinatorial Optimization and Applications, 2010.
關鍵點在於把vertex-disjoint paths與dominator兩個概念連結在一起。
【待補文字】
Diameter, Radius
程度★★ 難度★
Eccentricity
eccentricity(i) = max d(i, j)
j∊V
d(i, j) 為i點到j點的最短路徑
在一張無向圖上面,給定圖上一點,以最短路徑長度當作距離,找出離此點最遠的一點,這兩點之間的距離就叫做「偏心距」。
Diameter, Radius
diameter(G) = max eccentricity(i) = max d(i, j)
i∊V i,j∊V
radius(G) = min eccentricity(i)
i∊V
一張無向圖的「直徑」是圖上所有偏心距當中最大的一個,一張無向圖的「半徑」是圖上所有偏心距當中最小的一個。「直徑」也可以直接想做是,一張圖上長度最長的一條最短路徑之長度。
【註:有時候為了方便,直徑和半徑會定義成一段路徑,而不是一個數值。】
一張圖可能會有許多條直徑、許多條半徑。
直徑和半徑都是最短路徑。根據最短路徑的性質,直徑和半徑中間截一段路徑下來,也都會是最短路徑。
要計算一張無向圖的直徑與半徑是很簡單的,首先算好所有兩點之間最短路徑,然後按照定義來算就可以了。
延伸閱讀:樹的直徑與半徑
樹的直徑與半徑可以利用DFS求得,詳情請看本站文件「Tree」。
Center, Absolute Center
程度★★ 難度★★
Center
center(G) = arg min eccentricity(i)
i i∊V
= arg min max d(i, j)
i i∊V j∊V
d(i, j) 為i點到j點的最短路徑
一張無向圖的「中心」是圖上的一個點,離中心最偏遠的點,其距離會最小,也就是說「中心」的偏心距會等於半徑長度。一張無向圖可能會有很多個「中心」。
中心離圖上所有點越近越好,圖上所有點離中心越近越好。是以最偏遠的點的距離來衡量遠近,而非以各點的距離總和來衡量遠近。
要找到一張無向圖的中心是很簡單的,首先算好所有兩點之間最短路徑,然後按照定義來找就可以了。
Absolute Center
absolute_center(G) = arg min eccentricity(i)
i i
= arg min max d(i, j)
i i j∊V
一張無向圖的「絕對中心」,與中心稍有不同。絕對中心不一定得是原圖上的點,它可以位於某條邊上的某處。一張無向圖可能會有很多個「絕對中心」。
要找到一張無向圖的絕對中心,方法不多。目前最快的演算法,便是下述的演算法。
演算法(Kariv-Hakimi Algorithm)
此演算法跟一般圖論問題的解題手法完全不同。首先忘掉圖論,讓我們回到高中函數。
我們先假設絕對中心在邊ij上面。接著畫出一個函數圖形:X軸是絕對中心與i點的距離(想當然X軸範圍只有0到d(i,j)),Y軸是絕對中心與圖上x點的最短距離。先隨便選一個x點。
根據絕對中心在邊ij上面的各種位置,我們都可以算出絕對中心離x點的最短距離,進而描出一條函數線。這條函數線長得什麼樣子呢?以下分為三種情況討論:
甲、絕對中心在正權重的邊上游移:
觀察絕對中心到x點的最短距離變化。絕對中心挪往邊ij的中間,絕對中心到x點的最短距離就會慢慢增加;絕對中心挪往邊ij的兩端,絕對中心到x點的最短距離就會慢慢減少。左右的坡度是相同的,也可能只有左坡或者只有右坡。
接著觀察絕對中心到圖上每一點的最短距離變化。我們可以把每一個點的函數線統統描在同一張函數圖形,每條線的坡度都是一樣的。
根據絕對中心的定義,絕對中心與最遠點的距離越小越好;對照到函數圖形,就是上方邊際線的Y軸座標越低越好。由此可知,上方邊際線的最凹處,就是絕對中心的偏心距大小;最凹處的投影位置,就是絕對中心的最佳位置。窮舉上方邊際的所有凹處,找出最小的偏心距,就能找到絕對中心。
該如何找到上方邊際線的最凹處呢?這就要一點小技巧了。首先把每一條函數線的左端點按照高低排序,然後由最高的函數線開始,不斷與更低的函數線相交,交點即是上方邊際線的凹處。每次求得交點後,就留下原本較低的函數線,繼續與更低的函數線相交,最後就能得到所有凹處。Y軸座標最低的,就是最凹處了。
計算凹處的Y軸座標很簡單,只需要知道相交的兩條線在X軸的兩端分別有多高,就能推導出來了:
eccentricity(c)
= d(c, i) + d(i, x)
= d(c, j) + d(j, y)
= {d(i, j) + d(i, x) + d(j, y)} / 2
乙、絕對中心在負權重的邊上游移:
X軸左右兩端最高的函數線的交叉點,就是上方邊際線的最凹處。輕鬆寫意。
丙、絕對中心在零權重的邊上游移:
函數線都是水平線,最高的函數線到處都是最凹處。
最後,要找到一張無向圖的絕對中心,只需窮舉圖上所有邊,看看絕對中心在哪一條邊,再來依照方才的分析過程,取偏心距最小者即可。
一、計算所有兩點之間最短路徑。 並且紀錄起點到圖上各點的最短路徑長度順序。 二、窮舉圖上所有邊ij,找出絕對中心: 甲、正邊:i點、j點、上方邊際所有凹處。O(V)。 乙、負邊:i側最高線與j側最高線的交叉點。O(1)。 丙、零邊:最高的水平線。O(1)。
時間複雜度
一、計算所有兩點之間最短路徑:有負邊,則以Minimum Weight T-join求解,需時O(V^4)。無負邊,則執行V次Dijkstra's Algorithm,以Fibonacci Heap實作,需時O(V * (E + VlogV))。
二、尋找絕對中心:圖的資料結構是adjacency lists,需時O(VE)。
時間複雜度取決於計算最短路徑的時間。
實作
下面提供一個簡化過的實作,假設圖上的邊都是正權重。
這段程式碼沒有特別去紀錄絕對中心的位置,各位可以試著想一下怎麼紀錄。
延伸閱讀:無權重圖的絕對中心
簡單來說,就是每一條邊的權重都是一。在這種情況下,要尋找絕對中心的位置就簡單多了,判斷方式會變得簡潔一點。
先判斷左右兩側最高點是否一樣高。 甲、如果不一樣高,上方邊際線就出來了,答案也就出來了。O(1)。 乙、如果一樣高,則需要判斷上方邊際線的凹凸。 檢查左右兩側最高點,是不是來自同一點的最短路徑長度,若是則為凸。O(V)。
計算兩點之間最短路徑,只需V次BFS,需時O(VE)。尋找絕對中心,仍需時O(VE)。整體時間複雜度可降至O(VE)。