原文鏈接 http://dongzi85.blog.163.com/blog/static/8079890520089288468222/
最短路徑算法
分類:
- 無迴路網絡:拓撲排序法
- 無負權網絡:Dijkstra算法,Bellman-Ford算法
- 帶負權網絡:Bellman-Ford算法
- 所有點對之間的最短路徑:Floyd-Warshall算法
在圖中存在負權的情況下,最短路徑不一定存在。可以證明:
- [定理]:在無向連通圖中,兩點間的最短路徑存在當且僅當不含負權圈(往死裏轉吧,無窮小)。
Bellman Ford算法(SSSP):
基本思想:如果兩點間有最短路,那麼每個頂點最多經過一次。如果一個頂點經過兩次,那麼必定走了一個圈,如果這是個正圈,顯然是不合算的;如果是負圈,則根據上述定理,不存在最短路徑。
初始化d[起點]=0,d[其他點]= 無窮
for k=1 to n-1 do
for 每條邊 (u,v) do
if (d[u]<無窮) and (d[u]+w(u,v)<d[v])then d[v]=d[u]+w(u,v);
時間複雜度O(mn)。
Floyd-Warshall算法(ASSP):
求多源、無負權邊的最短路。用矩陣記錄圖。時效性較差,時間複雜度O(V^3)。
Floyd-Warshall算法(Floyd-Warshall algorithm)是解決任意兩點間的最短路徑的一種算法,可以正確處理
有向圖最短路徑問題。
Floyd-Warshall算法的時間複雜度爲O(N^3),空間複雜度爲O(N^2)。
Floyd-Warshall的原理是動態規劃:
考慮最短路的最優子結構性質。設d[i,j,k]是從節點i到節點j的最短路徑,且只允許經過[1...k]中的節點,考察節點k,有兩種情況:
- 經過k:則d[i,j,k]=d[i,k,k-1]+d[k,j,k-1]
- 不經過k:則d[i,j,k]=d[i,j,k-1]
for k=1 to n do
for i=1 to ndo
for j=1 to ndo
if (d[i,k]<無窮) and(d[k,j]<無窮)andd[i,k]+d[k,j]<d[i,j]then
d[i,j]=d[i,k]+d[k,j];
時間複雜度爲O(n3).
最短路算法總結:
- 標號修正算法(Bellman-Ford):算法迭代式的,標號都是臨時的,算法思想是不斷逼近最優解,最後一步達到最優解。
- 標號設定算法(Dijkstra):算法執行過程就是不斷把臨時標號設定成爲永久標號的過程。
- 標號設定算法時間複雜度低,但適用範圍小,例如Dijkstr算法就不適用於含負權邊的情況。標號修正算法適用範圍相對較廣,但時間複雜度較高。
附模板(原文鏈接 http://www.cnblogs.com/touchsunlight/archive/2010/08/09/1795816.html)
完全最短路徑(Floyd算法):[複雜度:O(n^3)]
|
單源最短路徑Dijkstra算法:
Bellman-Ford算法:
適用範圍:
- 單源最短路徑(從源點s到其它所有頂點v);
- 有向圖&無向圖(無向圖可以看作(u,v),(v,u)同屬於邊集E的有向圖);
- 邊權可正可負(如有負權迴路輸出錯誤提示);
- 差分約束系統;
算法描述:
- 對每條邊進行|V|-1次Relax操作;
- 如果存在(u,v)∈E使得dis[u]+w<dis[v],則存在負權迴路;否則dis[v]即爲s到v的最短距離,pre[v]爲前驅。