單源最短路徑

2021-07-27 15:43:42 字數 3205 閱讀 6610

在最短路徑問題中,給定乙個帶權重的有向圖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。

最短路徑存在幾個變體:

最短路徑演算法通常依賴最短路徑的乙個重要性質:兩個結點之間的一條最短路徑包含著其它的最短路徑。在某些單源最短路徑問題中可能包括權重為負值的邊。如果從結點s到結點v的某條路徑上存在權重為負值的環路,則定義δ=(u,v)=-∞。

在通常情況下,不但需要計算出最短路徑權重,還需要計算出最短路徑上的結點。給定圖g=(v,e),對於每個結點v,維持乙個前驅結點v.π,該前去結點可能是另乙個結點或者nil。最短路徑演算法將對每個結點的π屬性進行設定,這樣,將從結點v開始的前驅結點鏈反轉過來,就是從s到v的一條最短路徑。給定結點v,且v.π≠nil,print_pat(g,s,v)列印出的就是從結點s到結點v 的一條最短路徑。

但是,在執行最短路徑演算法的過程中,π值並不一定能給出最短路徑。定義結點集vπ為圖g中的前驅結點不為nil的結點的集合,再加上源結點s,即vπ=∪。有向邊集合eπ是由vπ中的結點的π值所誘導的邊的集合,即eπ=}。

單源最短路徑演算法所生成的π值具有如下性質:在演算法終止時,gπ是一棵「最短路徑樹」。非形式化的說,最短路徑樹是一棵具有根結點的樹,該樹包括了從源結點s到每個可以從s到達的結點的一條最短路徑。設g=(v,e)是帶權重的有向圖,其權重函式為w:e→r,假定g不包含從s可以到達的權重為負值的環路。一棵根結點為s的最短路徑樹是乙個有向子圖g』=(v』,e』),滿足:

需要指出的是,最短路徑不一定是唯一的,最短路徑樹葉不一定是唯一的。

對於每個結點v來說,為乙個屬性v.d用來記錄從源結點s到結點v的最短路徑權重的上界,稱v.d為s到v的最短路徑估計。使用如下的演算法來對最短路徑估計和前驅結點進行初始化:

initialize_single_source(g, s)

for each vertex v ∈ g.v

v.d = ∞

v.π = nil

s.d = 0

對一條邊(u,v)的鬆弛過程為:將從結點s到u之間的最短鉅鹿加上結點u和v之間的權重,並與當前的s到v的最短路徑估計進行比較,如果前者更小,則對v.d和v.π進行更新。

relax(u,v,w)

if v.d > u.d + w(u,v)

v.d = u.d + w(u,v)

v.π = u

最短路徑和鬆弛操作的一些性質如下:

bellman-ford演算法解決的是一般情況下的單源最短路徑問題,邊的權重可以為負值。給定帶權重的有向圖g=(v,e)和權重函式w:e→r,bellman-ford演算法返回乙個布林值,以表明是否存在乙個從源結點可以到達的權重為負值的環路。如果存在這樣的乙個環路,演算法將告訴我們不存在解決方案。如果沒有這種環路存在,演算法將給出最短路徑和它們的權重。

bellman-ford演算法通過對邊進行鬆弛操作來漸近的降低從源結點s到每個節點v的最短路徑的估計值v.d,知道該估計值與實際的最短路徑權重δ(s,v)相同時為止。該演算法返回true值當且僅當輸入圖不包含可以從源結點到達的權重為負值的環路。

bellman_ford(g, w, s)

initialize_single_source(g, s)

for i = 1

to |g.v – 1|

foreach edge(u,v) ∈g.e

relax(u, v, w)

foreach edge(u,v) ∈ g.e

if v.d > u.d + w(u,v)

return

false

return

true

乙個運用bellman-ford演算法的過程示例如下圖所示。

dijkstra演算法解決的是帶權重的有向圖上單源最短路徑問題,該演算法要求所有邊的權重都為非負值。

dijkstra演算法在執行過程中維持的關鍵資訊是一組結點集合s。從源結點s到該集合中每個結點之間的最短路徑已經被找到。演算法重複從結點集v-s中選擇最短路徑估計最小的結點u,將u加入到集合s,然後對所有從u出發的邊進行鬆弛。使用乙個最小優先佇列q來儲存集合,每個結點的關鍵值為其d值。

dijkstra(g, w, s)

initialize_single_source(g, s)

s = null

q = g.v

while q ≠ null

u = extract_min(q)

s = s ∪

foreach vertex v ∈ g.adj[u]

relax(u, v, w)

乙個執行該演算法的過程示例如下圖所示。

根據結點的拓撲排序次序來對帶權重的有向無環圖g=(v,e)進行邊的鬆弛操作,便可以計算出從單個源結點到所有結點之間的最短路徑。在有向無環圖中,即使存在權重為負值的邊,但因為沒有權重為負值的環路,最短路徑都是存在的。

首先對有向無環圖進行拓撲排序,確定結點之間的乙個線性次序。如果有向無環圖包含從結點u到結點v的一條路徑,則v在拓撲排序的次序中位於結點v的前面。只需要按照拓撲排序的次序對結點進行一遍處理即可。每次對乙個結點進行處理時,對從該結點出發的所有的邊進行鬆弛操作。

dag_shortest_paths(g, w, s)

topologically sort

the vertices of g

initialize_single_source(g, s)

foreach vertex u, taken in topologically sorted order

foreach vertex v ∈ g.adj[u]

relax(u, v, w)

乙個執行該演算法的過程示例如下圖所示。

單源最短路徑

include define max 999 define maxverts 10 typedef struct graph void chushi graph g void dij graph int key,int int int main for i 1 i g.numverts i dij ...

單源最短路徑

最優子結構 最短路徑的子路徑也是最短路徑,動態規劃和貪心演算法的乙個重要指標。環路 一條最短路徑不可能包含環路 1 環路權重為負,如果有一條環路權重為負,則不存在最短路徑 2 環路權重為零,如果包含該環路,則將該環路去掉即可 3 環路權重為正,去掉改環路可以得到更短的路徑,因此不可能是最短路徑 最短...

單源最短路徑

單源最短路徑問題,即在圖中求出給定頂點到其他任一頂點的最短路徑。1.最短路徑的最優子結構性質 該性質描述為 如果p i,j 是從頂點i到j的最短路徑,k和s是這條路徑上的乙個中間頂點,那麼p k,s 必定是從k到s的最短路徑。證明 假設p i,j 是從頂點i到j的最短路徑,則有p i,j p i,k...