描述:單源 最短路徑(找到指定頂點到其餘各點的最短路徑)
思想:greedy
時間複雜度:o(n^2)
空間複雜度:o(n)
關鍵:每次將v-u內到起點最短的頂點加入到u,並且嘗試作為中轉點,縮短起點到v-u其他頂點的距離
這樣做,下一條構成的路徑(設終點為x),必然是v0到vx的最短路徑,且必定是b2或者是b1+b2。即,v0到vx的最短路徑不會是通過a1 + a2 + a3這種方法產生的
u表示已找出的,從v0出發的,最短路徑的終點;v-u是待找出的
(1:所有頂點都在u內的路徑;
2:連通u和v-u的弧
3:所有頂點都在v-u內的路徑;
vx表示頂點,
a2表示某條連通u和v-u的弧
a1表示連通起點到弧a2的在u裡的頂點的路徑
a3表示連通弧a2的在v-u裡的頂點到終點的路徑
簡要證明:
按照這個過程,會存在一條比b2/b1+b2演算法更短的路徑,那就只能是a1 + a2 + a3,而a1 + a2 + a3比b2/b1+b2小意味著a2必須小於b2,但這與b2的語義(b2是當前連通u和v-u最短的弧) 相矛盾
詳細證明:(反證法:要證v0到x可能是通過a1 + a2 + a3產生的)
假設v0到x的最短路徑的構成是成分是a1 + a2 + a3,則a1 + a2 + a3必然小於b2,且a1 + a2 + a3必然小於任意一條b1+b2。
如果a1 + a2 + a3 < b2,那麼a1,a2,a3三個成分至少有乙個是小於b2的。
然後你就突然發現,只要允許路徑權值和為負值的話,這沒有任何毛病,沒辦法反證!!只有所有弧的權值》=0證明才能成立。
在所有弧的權值都》=0前提下
》對於a1 + a2 + a3 < b2的推論:
a1,a2,a3必須都小於b2,但既然a21.最小生成樹的任意兩點之間的路徑是不是連通這兩點的最短路徑?(這也是dijkstra跟prim的區別所在)
答:不是,由下圖可知,a和b都是最小生成樹,但a中從v0到v3路徑長6,b中v0到v3路徑長4
2.在將頂點從v-u加入到u過程中,是選擇v0到v-u最短的路徑,還是選擇u到v-u最短的路徑
答:選擇v0到v-u最短的路徑,道理同上,如果只考慮u到v-u而不從這條路徑考慮,遇到這種和弧相等的情況就沒辦法準確的抉擇
3.(假設在乙個連通圖里)按迪傑斯特拉方法將某點到其餘所有頂點的最短路徑都建立完後,是不是一棵最小生成樹
(假設在乙個無向連通圖里)首先最短路徑都建立完後,肯定是乙個連通圖,因為所有點都和v0連通,而連通是可傳遞的
其次,它肯定是一棵生成樹,否則它必定有環(連通但不是極小意味著有環)但這跟「只要頂點被加入u,v0到它的最短路徑就已經被找到」的結論不符合
然後它也是最小生成樹。假設它不是mst,
解釋1:那麼在v0到達某點vx之間必定存在另一條更短的路徑,但這是不可能大,正如上面說,如果這另一條是v0直達vx的,就一定是「選v-u中v0到它路徑最短的點」的結果;如果是其他點v間接到達的,因為v0到v肯定比v0到vx更快,所以v必然在vx之前就加入到u了
解釋2:那麼某點vx被加入u時選擇的必然是另一條更短的路徑,且並非b1+b2或b2產生的結果;
那就只能是a1+a2+a3這種方法的結果了,但這樣被a2連通的節點必定先於vx被加入u,也就是說,實際上會演變成b1+b2的情況
注意,迪傑斯特拉的完整過程,是找到乙個起點到其餘所有頂點的最短路徑,如果只希望找到指定終點的最短路徑,最糟糕的情況下,需要先找到前面所有頂點的最短路徑
其實,dijkstra和prim的思想十分類似,都是貪心演算法的思想,我自己想的時候,都是先將需要的資料準備好。但這兩種方法的精妙之處,就在於需要的資料是一邊更新狀態一邊獲取的。
#define inf int_max
struct edge
edge
(int begin,
int end,
int weight):b
(begin),e
(end),w
(weight)};
struct adjmatrix};
list
dijkstra
(const adjmatrix& mat,
int src,
int dst)
;int n = mat.vn;
list path;
vector<
bool
>
vs(n,
false);
vector<
int>
prev
(n, src)
; vector<
int>
minarc
(n, inf)
; minarc[src]=0
; vs[src]
=true
; prev[src]=-
1;int k =1;
int v = src;
while
(k <= n -1)
if(minarc[i]
< minw)}if
(nextv ==-1
)break
; v = nextv;
vs[v]
=true;if
(v == dst)
break
;++k;}if
(v == dst)
// 回溯構建路徑
while
(pv != src);}
return path;
}
int
main()
,,,,
,}; adjmatrix mat
(m);
auto l =
floyd
(mat)
;getchar()
;return0;
}
迪傑斯特拉 Dijkstra
參考 迪傑斯特拉 dijkstra 演算法是典型最短路徑演算法,用於計算乙個節點到其他節點的最短路徑。它的主要特點是以起始點為中心向外層層擴充套件 廣度優先搜尋思想 直到擴充套件到終點為止。大概就是這樣乙個有權圖,dijkstra演算法可以計算任意節點到其他節點的最短路徑 演算法思路 指定乙個節點,...
Dijkstra 迪傑斯特拉
1 演算法思想 設g v,e 是乙個帶權有向圖,把圖中頂點集合v分成兩組 第一組為已求出最短路徑的頂點集合 用s表示,初始時s中只有乙個源點,以後每求得一條最短路徑 就將加入到 集合s中,直到全部頂點都加入到s中,演算法就結束了 第二組為其餘未確定最短路徑的頂點集合 用u表示 按最短路徑長度的遞增次...
Dijkstra(迪傑斯特拉)演算法
迪傑斯特拉 dijkstra 演算法是典型最短路徑演算法,用於計算乙個節點到其他節點的最短路徑。它的主要特點是以起始點為中心向外層層擴充套件 廣度優先搜尋思想 直到擴充套件到終點為止。指定乙個節點,例如我們要計算 a 到其他節點的最短路徑 引入兩個集合 s u s集合包含已求出的最短路徑的點 以及相...