圖論,最短路徑問題總結

來源:互聯網
上載者:User

標籤:最短路徑   最短路   floyd   dijkstra   

維基百科定義最短路:

一個有6個節點和7條邊的圖

最短路徑問題是圖論研究中的一個經典演算法問題, 旨在尋找圖(由結點和路徑組成的)中兩結點之間的最短路徑。 演算法具體的形式包括:

  • 確定起點的最短路徑問題 - 即已知起始結點,求最短路徑的問題。適合使用Dijkstra演算法。
  • 確定終點的最短路徑問題 - 與確定起點的問題相反,該問題是已知終結結點,求最短路徑的問題。在無向圖中該問題與確定起點的問題完全等同,在有向圖中該問題等同於把所有路徑方向反轉的確定起點的問題。
  • 確定起點終點的最短路徑問題 - 即已知起點和終點,求兩結點之間的最短路徑。
  • 全域最短路徑問題 - 求圖中所有的最短路徑。適合使用Floyd-Warshall演算法。

用於解決最短路徑問題的演算法被稱做“最短路徑演算法”, 有時被簡稱作“路徑演算法”。 最常用的路徑演算法有:

  • Dijkstra演算法
  • A*演算法
  • Bellman-Ford演算法
  • SPFA演算法 (Bellman-Ford演算法的改進版本)
  • Floyd-Warshall演算法
  • Johnson演算法
  • Bi-Direction BFS演算法

1.floyd演算法 (n^3複雜度)


基本思想:開始設集合S的初始狀態為空白,然後依次將0,1,。。n-1定點加入,同時用d[i][j]儲存從i到j,僅經過S中的定點的最短路徑,在初始時刻,d[i][j] = A[i][j]中間不經過任何節點,然後依次向S中插入節點,並進行如下更新
d(k)[i][j] = min{  d(k-1)[i][j] ,  d(k-1)[i][k]+d(k-1)[k][j]  }
還可以使用一個二維數組path指示最短路徑。
path[i][j]給出從定點i到j的最短路徑上,定點i的前一個頂點
代碼相當簡單,最容易的實現方法:

for (k = 0;k < n;k++)for (i = 0;i < n;i++)for (j = 0;j < n;j++){if (d[i][k] + d[k][j] < d[i][j]){d[i][j] = d[i][k] + d[k][j];path[i][j] = path[k][j];}}

可以通過遞推得出路徑的。。

2.dijstra演算法

單源最短路問題,先加入源,維持一張表來儲存此時到源中的最短距離,選取最小的加入,然後更新表,不斷的加入直到目的地在源中。僅適用於正邊權的時侯,因為這時我們可以保證任意加入的點已經找到了源到該點的距離。

 

3.bellman-ford演算法

 

最優性原理

最優性原理介紹及簡單證明見:http://blog.csdn.net/liguanxing/article/details/7401798

它是最優性原理的直接應用,演算法基於以下事實:

如果最短路存在,則每個頂點最多經過一次,因此不超過n-1條邊;

長度為k的路由長度為k-1的路加一條邊得到;

由最優性原理,只需依次考慮長度為1,2,…,k-1的最短路。

 

適用條件&範圍

單源最短路徑(從源點s到其它所有頂點v);

有向圖&無向圖(無向圖可以看作(u,v),(v,u)同屬於邊集E的有向圖);

邊權可正可負(如有負權迴路輸出錯誤提示);

 差分約束系統(需要首先構造約束圖,構造不等式時>=表示求最小值,作為最長路,<=表示求最大值,作為最短路。<=構圖時,有負環說明無解;求不出最短路(為Inf)為任意解。>=構圖時類似)。  

 

演算法描述

 1)對每條邊進行|V|-1次Relax操作;

 2)如果存在(u,v)∈E使得dis[u]+w<dis[v],則存在負權迴路;否則dis[v]即為s到v的最短距離,pre[v]為前驅。  

 

for i:=1 to |V|-1 do //進行|v|-1次鬆弛得最短距離    for 每條邊(u,v)∈E do           Relax(u,v,w);for每條邊(u,v)∈E do //判斷是否存在負權環    if dis[u]+w<dis[v]         Then Exit(False)

演算法時間複雜度O(VE)。因為演算法簡單,適用範圍又廣,雖然複雜度稍高,仍不失為一個很實用的演算法。  

改進和最佳化  如果迴圈n-1次以前已經發現不存在緊邊則可以立即終止;

 

 

4.spfa演算法

SPFA(Shortest Path Faster Algorithm)是Bellman-Ford演算法的一種隊列實現,減少了不必要的冗餘計算。它可以在O(kE)的時間複雜度內求出源點到其他所有點的最短路徑,可以處理負邊。

 

 

演算法流程  

SPFA對Bellman-Ford演算法最佳化的關鍵之處在於意識到:只有那些在前一遍鬆弛中改變了距離估計值的點,才可能引起他們的鄰接點的距離估計值的改變。因此,演算法大致流程是用一個隊列來進行維護,即用一個先進先出的隊列來存放被成功鬆弛的頂點。初始時,源點s入隊。當隊列不為空白時,取出隊首頂點,對它的鄰接點進行鬆弛。如果某個鄰接點鬆弛成功,且該鄰接點不在隊列中,則將其入隊。經過有限次的鬆弛操作後,隊列將為空白,演算法結束。SPFA演算法的實現,需要用到一個先進先出的隊列 queue 和一個指示頂點是否在隊列中的標記數組mark。為了方便尋找某個頂點的鄰接點,圖採用臨界表格儲存體。


Procedure SPFA; Begin   initialize-single-source(G,s);   initialize-queue(Q);   enqueue(Q,s);   while not empty(Q) do begin      u:=dequeue(Q);      for each v∈adj[u] do begin         tmp:=d[v];         relax(u,v);         if (tmp<>d[v]) and (not v in Q) then enqueue(Q,v);         end;      end;End;

注意:spfa演算法只有在不存在負權環的情況下可以正常的結束,如果存在負權環,那麼將總有頂點在入隊和出隊往返,隊列無法為空白,這種情況下SPFA無法正常結束。可以通過添加一個變數表示每個頂點進入隊列的次數,如果大於|v|那麼就可以說明存在負權環



圖論,最短路徑問題總結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.