Dijkstra和Floyd演算法

2021-05-23 07:38:42 字數 2609 閱讀 6150

floyd

演算法:

如果要求所有兩結點間的最短路徑,則可以使用

dijkstra演算法n

次完成,時間複雜度是

o(n^3)

,floyd

還提出過另乙個演算法,同樣是

o(n^3)

的複雜度,但形式上更簡單些。

要求的解是乙個矩陣s

[n][n]

,其中s[i][j]

表示結點i到

j的最短路徑,演算法很像動態

規劃演算法,甚至更簡單些,不同的是這裡規劃的是乙個矩陣,而不是簡單的陣列。

floyd

演算法過程描述如下:

(在整個迴圈結束後,

s[i][j]

肯定是i和j

之間的最短路徑——

i如果和

j之間有直接通路,但是比

s[i][k]+s[k][j]

長的話就會被

s[i][k]+s[k][j]

替換,而

s[i][k]

(或s[k][j]

)可能也是中間經過某乙個其他點(這邊設為

w點)而得到的i到

k的最短路徑,所以可能i到

j的最短路徑是由

s[i][k]+s[k][j]

得到,而

s[i][k]

又是由i到w

再到k的(s[k][j]

同理),因此i到

j的最短路徑就可能是i—

>w

—>k

—>j

的(這邊假設

s[k][j]

中間沒有經過其他點,自己就是最短的))

1、首先s以邊集m初始化,得到所有的直接連通代價;

2、依次考慮第

k個結點,對於s中的每乙個s

[i][j]

,判斷是否滿足:

s[i][j]>s[i][k]+s[k][j]

,如果滿足則用

s[i][k]+s[k][j]

代替s[i][j]

,此為第k步;

3、k迴圈取遍所有結點,演算法結束時,s為最終解。

這樣的求法自然再簡單不過了,但要證明其中的正確性,有些難度,為什麼不會使結點

重複存在於同一路徑?在替換的時候,

s[i][k]

和s[k][j]

中如果同時含有

m結點,則這樣的替

換顯然是錯誤的,相當於

i-->m-->k-->m-->j

,可以簡單用這有這樣連通關係的例子試一下,會

發現如果在一條路徑中有結點冗餘,則不可能是最短路徑,顯然上面這條有冗餘結點的路徑

肯定要比

i-->m-->j

要長,所以演算法在要求最短的同時已經排除了這種情況,這樣使得任意一

條路徑都不冗餘。

dijikstra

演算法:

(dijkstra

可以處理負權邊,不允許有負權環,否則可以通過不斷走負權環取得更小值。如果要考慮權值為負的情況可以用

bellman-ford

演算法來實現)

大體過程如下:(過程中涉及到乙個

s集合用來儲存已經求出到源點的最短路徑的點,乙個

u集合,儲存還沒有求出到源點最短路徑的點(即全部點的集合

a減去集合

s所得的集合))

1、先將源點v加入

s集合中;

2、在剩下的

u集合中找到與

v有直接關聯的邊且其權值最小的點,先將該直接邊的權值作為該點暫時的最短路徑,將

s集合裡面的各個點與這點關聯起來(如果有直接關聯的邊的話),看從源點

v到該點(中間經過若干

s集合中的點)的權值之和是不是小於

v與該點間直接邊的權值,如果小於的話就替換該點的最短路徑;3、看

u集合中還有沒有點,如果有的話則重複步驟

2,否則演算法結束

注:在進行上述演算法前如果先對各個點之間的權值大小進行排序可以提高演算法效率,在步驟

2中「在剩下的

u集合中找到與

v有直接關聯的邊且其權值最小的點」時可以不用每次都遍歷所有的邊。

再注:每一次向

s中加入乙個點之後,對於

u集合中的

j點的原始最短路徑值(與源點有直接關聯邊的就是直接關聯邊的權值,沒有的話就是無窮大)的影響:如果有影響,那影響後的路徑肯定是先經過

s集合中的某些點然後再經過剛剛加入

s集合的點再直接到

j點,而不可能是先經過

s集合中的某些點再經過剛剛加入

s集合的點,再經過

s集合中的其他點(設為

x點)再到

j點的,因為如果是這樣的話那剛剛加入

s集合的點(設為

k點)應該在

x之前就已經加入

s集合了的,因為x在

k之前加入

s集合,所以

vx的路徑長度肯定大於

vkx的路徑長度,而後面加

j的時候都是加上

xj的長度,這個顯然不合理了的。

最短路 Floyd演算法和Dijkstra演算法

兩者在負權問題上不是很好,最好只處理正值,dijkstra演算法對負權毫無辦法,但是floyd演算法不能處理出現負環的東西。dijkstra演算法的話,為了方便,我認為從i到i點不可達 百部百科解釋挺好,那個堆優化挺好的 floyd演算法百部百科也不錯,都是老演算法了,哪都有資料 這位筒子的寫得很好...

Dijkstra和Floyd演算法

floyd演算法 如果要求所有兩結點間的最短路徑,則可以使用dijkstra演算法n次完成,時間複雜度是 o n 3 floyd還提出過另乙個演算法,同樣是o n 3 的複雜度,但形式上更簡單些。要求的解是乙個矩陣 n n 其中s i j 表示結點i到j的最短路徑,演算法很像動態 規劃演算法,甚至更...

Floyd和Dijkstra演算法

floyd演算法 演算法解析 因為一張連通圖中不是所有點到其他點都是有一條直接路徑的,所以我們可以借助別的和終點相連的點到達終點,便是起點 中轉 終點 以小推大,小 假設當前只有1可以當中轉點,start為起點,end為終點 因此當start點需要借助點1到end點時,便需要進行if edge st...