演算法和資料結構之最短路徑演算法

2021-10-16 22:12:57 字數 3932 閱讀 3264

references

通常,我們發現沿著圖中的一條邊移動會有一些相關的成本(或利潤),例如邊的距離,汽油的**,花費的時間等等。

我們稱這之為加權圖,稱邊值為權值。

我們將之前的圖定義擴充套件如下:

加權圖g由有序序列(v, e, w)組成,其中v和e是頂點和邊,w是邊的權值。

w((a, b))=50, w((a, c))=30等等。

同時我們可以用圖的鄰接矩陣表示為:

「-」表示邊緣不存在。

與加權圖有關的乙個常見問題是尋找頂點之間的最短路徑。

該演算法的工作原理是將頂點分為兩個集合,s和c。

在每個迭代;s包含已經被選擇的節點集。

s也叫做選擇集 selected set.

在每個迭代;c包含了一組尚未被選中的節點:

c也叫做候選集 candidate set.

在每一步中,我們將到達c的最小節點移動到s。

我們還需要乙個函式d使d(ci)是我們目前找到的候選集合c中從頂點s到頂點ci的最短距離。

舉個例子:

我們現在選擇d的最小值,d(e)=10。

step 1:

我們將頂點e從c移動到s。

s=c=

d()= 20, 30, 50

a到d有兩條,一條為a-e-d:10+10=20,另一條是a-d=100,20<100所以我們不需要在d()中再加入100,後面出現這種情況同理。

我們現在選擇d的最小值,d(d)=20。

step 3:

將頂點c從c移動到s。

s=c=

d()= 35 // a-c-b 30+5=35

我們現在選擇d的最小值,d(b)=35

step 4:

將頂點b從c移動到s

s=c={}

c中沒有候選頂點了,所以我們完成了。

適用於具有負邊權值的圖。

識別負迴圈和路徑上有負迴圈的頂點。

為所有其他頂點找到正確的路徑和路徑長度。

舉個例子:

上圖中a-c-b組成了乙個迴圈,這個迴圈的總權值為-1,這意味著如果按照剛才dijkstra』s algorithm來的話,所有路徑都可以重複走這個cycle讓自己權值降到最低。

因此我們如何用bellman-ford考慮呢?

與dijkstra演算法不同的是,dijkstra演算法在每次迭代時只更新最有希望的(下乙個成本最低的)頂點,bellman-ford在每次迭代中更新每個頂點。

這意味著bellman-ford的每次迭代都比dijkstra的迭代需要更多的工作。

拿上圖舉例:

它有6個頂點,所以我們將在主迴圈中執行5次。

初始化:

我們為d設定初始值:

d(s)=0sa

bcde

0∞∞∞

∞∞迭代1:

頂點 s: 我們可以到達a和e, 更新。

頂點 a: 我們可以到達c, 更新。

頂點 b: 我們還不能到達,跳過。

頂點 c: 我們可以到達b, 更新。

頂點 d: 我們還不能到達,跳過。

頂點 e: 我們可以到達d, 更新。

下表為第一次迭代結束後的權值:sa

bcde

010101238

迭代2:

頂點 s: 我們可以到達a和e, 沒有變化。

頂點 a: 我們可以到達c, 沒有變化。

頂點 b: 我們可以到達a,更新

頂點 c: 我們可以到達b, 沒有變化。

頂點 d: 我們可以到達a和c,更新。

頂點 e: 我們可以到達d, 沒有變化。

下表為第二次迭代結束後的權值:sa

bcde

0-1102

38注意:a現在的權值是s-e-d-a=8-5-4=-1

c現在的權值是s-e-d-c=8-5-1=2

後面同理。

迭代3:

頂點 s: 我們可以到達a和e, 沒有變化。

頂點 a: 我們可以到達c, 更新。

頂點 b: 我們可以到達a,沒有變化。

頂點 c: 我們可以到達b, 更新。

頂點 d: 我們可以到達a和c,沒有變化。

頂點 e: 我們可以到達d, 沒有變化。

下表為第三次迭代結束後的權值:sa

bcde

0-1-11

38迭代4:

頂點 s: 我們可以到達a和e, 沒有變化。

頂點 a: 我們可以到達c, 沒有變化

頂點 b: 我們可以到達a,更新。

頂點 c: 我們可以到達b, 沒有變化。

頂點 d: 我們可以到達a和c,沒有變化。

頂點 e: 我們可以到達d, 沒有變化。

下表為第四次迭代結束後的權值:sa

bcde

0-2-11

38迭代5:

頂點 s: 我們可以到達a和e, 沒有變化。

頂點 a: 我們可以到達c, 更新。

頂點 b: 我們可以到達a,沒有變化。

頂點 c: 我們可以到達b, 更新。

頂點 d: 我們可以到達a和c,沒有變化。

頂點 e: 我們可以到達d, 沒有變化。

下表為第五次迭代結束後的權值:sa

bcde

0-2-20

38五次迭代結束,

檢查:頂點 s: 我們可以到達a和e, 沒有變化。

頂點 a: 我們可以到達c, 把a標記為bad。

頂點 b: 我們可以到達a,沒有變化。

頂點 c: 我們可以到達b, 沒有變化。

頂點 d: 我們可以到達a和c,沒有變化。

頂點 e: 我們可以到達d, 沒有變化。sa

bcde

0x-20

38結論:我們可以得出結論,圖包含乙個包含頂點a的負成本迴圈。

如果我們從頂點a開始執行dfs(或bfs),將所有訪問過的頂點標記為bad,我們得到以下結果:sa

bcde

0***

38因此:頂點 a: 通過迴圈到達。

頂點 b: 通過迴圈到達。

頂點 c: 通過迴圈到。

頂點 d: 可到達的花費為3。

頂點 e: 可到達的花費為8。

公式:f(n)=g(n)+h(n),

f(n) 是從初始狀態經由狀態n到目標狀態的代價估計。

g(n) 是在狀態空間中從初始狀態到狀態n的實際代價。

h(n) 是從狀態n到目標狀態的最佳路徑的估計代價。

放在路徑搜尋問題中,狀態就是圖中的節點,代價就是距離或者權重。

a*的訣竅是找到乙個好的啟發式。

對頂點選擇規則的啟發式修改將dijkstra演算法變成了乙個被稱為a*演算法的例子。

儘管在最壞的情況下,a*並不比dijkstra更快,但在實踐中,它通常代表著實質性的改進。

從v到g的估計最小路徑長度h(v, g)與實際最小路徑長度p(v, g)越接近,a*就越快找到解。

introduction to the design and analysis of algorithms, a. levitin, 3rd ed., pearson 2011.

introduction to algorithms, t. h. cormen, 3rd ed, mit press 2009.

資料結構之最短路徑(DijKstra)

dijkstra 迪傑斯特拉 演算法是典型的最短路徑路由演算法,用於計算乙個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。dijkstra演算法能得出最短路徑的最優解,但由於它遍歷計算的節點很多,所以效率低。dijkstra演算法是很有代表性的最短路...

資料結構之最短路徑(Floyd)

floyd演算法,求網圖g中各頂點v到其餘頂點w的最短路徑p v w 及帶權長度d v w void shortestpath floyd mgraph g,patharc p,shortpathtable d 下面介紹下詳細的執行過程 1 程式開始執行,第4 11行就是初始化了d和p,使得它們成為...

資料結構之最短路徑問題

1.定義概覽 dijkstra 迪傑斯特拉 演算法是典型的單源最短路徑演算法,用於計算乙個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。dijkstra演算法是很有代表性的最短路徑演算法,在很多專業課程中都作為基本內容有詳細的介紹,如資料結構,圖論,...