寫在前面:好久沒看圖論了,今天寫作業的時候發現我已經忘記了。俗話說的好,好記性不如爛筆頭,我翻了翻之前的筆記,竟然沒有關於dijkstra的(手動狗頭)。趕緊連夜寫了一篇部落格,只為勾引我對dijkstra的些許記憶。從乙個頂點到其餘各頂點的最短路徑演算法,解決的是有權圖(不存在負權邊)中最短路徑問題
它是由e.w.dijkstra提出的一種按照路徑長度遞增的次序
分別產生到各頂點最短路徑的貪心演算法。
該演算法把帶權圖的的所有頂點分成兩個集合s和v-s。集合s中存放的是已經找到最短路徑的頂點。v-s中存放未找到最短路徑的頂點。演算法按照路徑長度遞增的次序。逐一將v-s中的元素移動到s中。直至v-s為空。
其中,用到乙個非常重要的原理:如果當前v0到vi的最短路徑已經找到,那該條路徑也一定是v0到路徑中所有點的最短路徑。換句話說,如果要找v0到vi的最短路徑,那麼在vi之前的i-1個頂點肯定已經找到最短路徑了,即i-1個頂點都在集合s中。
如圖中,0-4的最短路徑為0-1-7-8-2-5-4.那麼從v0到v8的最短路徑一定是0-1-7-8.
我們以8號結點為例,進行證明:dijkstra演算法按照從給定起點到圖中頂點的距離,順序求出最短路徑。首先求出從起點到最接近點的頂點之間的最短路徑。然後求出第二近的,一次類推。推而廣之,在第i次迭代開始以前,該演算法已經確定了i-1個頂點的最短路徑。假定上一次(第i-1次迭代)加入集合s的頂點為t。那麼在集合v-s中,與a相鄰的頂點集合稱為「邊緣頂點」,他們作為候選物件。而dijkstra演算法可以從這些候選物件中選出下乙個最接近源點v0的頂點,並把它移動到v-s集合中。假設v0-v8的最短路徑是0-7-6-8,那麼也就說明圖中紅色路徑的長度小於0-1-7-8的長度。
那麼從起點0-4的最短路徑就是下圖中的紅色所示。
這與前提不符合,即假設不合理,所以從v0到v8的最短路徑一定是0-1-7-8.
將所有的頂點分為兩部分:已知最短路徑的頂點集合s和未知最短路徑的頂點集合v-s。可考慮用book陣列實現,book[i]=1,可表示在s中,book[i]=0,則表示在s-v中。
初始化設定源點v0到自己的最短路徑為0.若存在有源點能直接到達的頂點i,就把v0-vi的最短路徑設定為對應的長度。同時把其他頂點的最短路徑設定為∞。同時book陣列清零。
在集合s-v中選擇乙個距離遠點最近的頂點i,加入到集合s中。並考察所有以i為起點的邊,對每一條邊進行鬆弛操作。例如存在一條從頂點u到頂點v的邊,則可通過u拓展一條從s到v的路徑即s -> u -> v,這條路徑的長度為dis[ u ]+e[ u ][ v ],如果這個值比dis[ v ]的值要小,我們可以用新值替代當前dis[ v ]中的值
如此重複第三步,如果集合v-s為空,則結束。最終dis陣列中的值就是源點到各點的最短路徑
void
dijkstra
(int s)
//s為源點即起點
} book[u]=1
;//頂點u已經確定最短距離,移入集合s,標記為1
//鬆弛:遍歷頂點u的邊緣頂點,借助剛確定的u頂點作為中轉點重新整理最短距離
for(j =
1;j <= n;j++)if
(e[u]
[j]< inf)
//如果u點到j點有路
//源點s到j點的距離大於借助u點中轉的距離(就是源點到u的距離加u到j的距離)
if(dis[j]
> dis[u]
+ e[u]
[j])
dis[j]
= dis[u]
+ e[u]
[j];
//更新源點到j頂點的最短距離
}}
tips:個人回憶小部落格,不足之處,希望大佬糾正。 Dijkstra 單源最短路徑
演算法思想 輔助陣列dis i 表示當前源頂點到i的最短路徑。dis i 在程式未結束前,類似於動態規劃,可更新以取得最小值 陣列path用來記錄路徑 首先初始化令dis i 為edge v0 i v0為源頂點 然後選擇離源頂點最小的路徑,加入到構造最短路徑的點集合中,然後看是否可以更新dis i ...
Dijkstra 單源最短路徑
演算法思想 輔助陣列dis i 表示當前源頂點到i的最短路徑。dis i 在程式未結束前,類似於動態規劃,可更新以取得最小值 陣列path用來記錄路徑 首先初始化令dis i 為edge v0 i v0為源頂點 然後選擇離源頂點最小的路徑,加入到構造最短路徑的點集合中,然後看是否可以更新dis i ...
Dijkstra單源最短路徑
dijkstra單源最短路徑 給定乙個帶權有向圖g v,e 其中每條邊的權是乙個非負實數。另外,還給定 v 中的乙個頂點,稱為源。現在我們要計算從源到所有其他各頂點的最短路徑長度。這裡的長度是指路上各邊權之和。這個問題通常稱為單源最短路徑問題。下面給出兩個計算單源最短路徑的模板。dijkstra 簡...