詳解 Dijkstra迪傑斯特拉演算法

2021-10-07 01:15:57 字數 3142 閱讀 6062

描述:單源 最短路徑(找到指定頂點到其餘各點的最短路徑)

思想: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集合包含已求出的最短路徑的點 以及相...