參考:
K條最短路徑算法:Yen's Algorithm
算法背景
K 最短路徑問題是最短路徑問題的擴展和變形。1959 年,霍夫曼(Hoffman) 和帕夫雷(Pavley)在論文中第一次提出k 最短路徑問題。 k 最短路徑問題通常包括兩類:有限制的k 最短路問題和無限制的K 最短路問題。 前者要求最短路徑集合不含有回路,而后者對所求得的最短路徑集合無限制。
算法簡介
Yen's算法是Yen 在1971 年提出的以其名字命名 的Yen 算法。Yen's算法采用了遞推法中的偏離路徑算法思想,適用於非負權邊的有向無環圖結構。
算法思想
算法可分為兩部分,算出第1條最短路徑P(1),然后在此基礎上依次依次算出其他的K-1條最短路徑。在求P(i+1) 時,將P(i)上除了終止節點外的所有節點都視為偏離節點,並計算每個偏離節點到終止節點的最短路徑,再與之前的P(i)上起始節點到偏離節點的路徑拼接,構成候選路徑,進而求得最短偏離路徑。
算法實例:
根據個人的理解,我歸納出了以下步驟:
調用K條最短路徑算法,源C,目的H,K為3。B為偏離路徑集合。
1.通過Dijkstra算法計算得到最短路徑A^1
:C-E-F-H
,其中,花費為5,A[1] = C-E-F-H
;
2.將A[1]作為迭代路徑,進行第一次迭代:
(1)以部分迭代路徑(即A[1])C
路徑中,C點為起點,將C-E
路徑之間的權值設為無窮大,進行一次Dijkstra,得到路徑A^2-1
:C-D-F-H
,花費為8,將A^2-1
路徑加入B;
(2)以部分迭代路徑(即A[1])C-E
路徑中,E為起點,將E-F
路徑之間的權值設為無窮大,進行一次Dijkstra,得到路徑A^2-2
:C-E-G-H
,花費為7,將A^2-2
路徑加入B;
(3)以部分迭代路徑(即A[1])C-E-F
路徑中,F為起點,將F-H
路徑之間的權值設為無窮大,進行一次Dijkstra,得到路徑A^2-3
:C-E-F-G-H
,花費為8,將A^2-3
路徑加入B;
迭代完成,B集合中有三條路徑:C-D-F-H
,C-E-G-H
,C-E-F-G-H
;選出花費最小的偏離路徑C-E-G-H
,A[2] = C-E-G-H
,移出B集合。
3.將A[2]作為迭代路徑,進行第二次迭代:
(1)以部分迭代路徑(即A[2])C
路徑中,C點為起點,將C-E
路徑之間的權值設為無窮大,進行一次Dijkstra,得到路徑A^3-1
:C-D-F-H
,但B集合已存在該路徑,故不存在偏移路徑;
(2)以部分迭代路徑(即A[2])C-E
路徑中,E點為起點,將E-G
、E-F
路徑之間的權值設為無窮大 (注意,這里設置兩條路徑的權值原因是這兩條路徑分別存在於A[1]和A[2]中),進行一次Dijkstra,得到路徑A^3-2
:C-E-D-F-H
,花費為8,將A^3-2
加入B;
(3)以部分迭代路徑(即A[2])C-E-G
路徑中,G點為起點,將C-H
路徑之間的權值設為無窮大,不存在偏移路徑。
迭代完成,B集合中有三條路徑:C-D-F-H
,C-E-F-G-H
,C-E-D-F-H
;由於三條路徑花費均為8,則根據最小節點數進行判斷,選出偏離路徑C-D-F-H
,A[3] = C-D-F-H
。
此時,選出了三條最短路徑,分別是:
A[1] = C-E-F-H
A[2] = C-E-G-H
A[3] = C-D-F-H
算法結束。以上過程均為個人理解,如果出現了偏差,請大家指出,謝謝!
算法實現
可以參考Github中的一個使用python實現KSP算法的repo:Yen's K-Shortest Path Algorithm
2017.8