1. 程式人生 > >最短路演算法總結

最短路演算法總結

對於最短路的學習,剛開始是做模板題,對於幾種演算法並不怎麼理解,後來逐漸的做題查資料中漸漸的有了一點自己的理解,對於最短路演算法,大致有以下幾種:

Dijkstra, Floyd, Bellman-Ford,SPFA幾種,這幾種演算法各有特點和用處,下面是我的一些理解。

  • Dijkstra演算法 :

首先,這種演算法的前提是權值圖中不存在負權邊,這個演算法的主要思想是貪心思想,Dijkstra演算法是單源最短路利用dis陣列儲存從起點到其他點的最短路,剛開始儲存的是起始點到其他點的初始路程,通過n-1次遍歷找到最短路, 該演算法通過n-1次的鬆弛使起始點到其他點的路程變為最小,演算法主題:if(mindis+Map[min][j]<dis[j] && Map[min][j]!=INF && vis[j]==0)
dis[j] = mindis+Map[min][j];

每次從dis陣列中選出一個值最小的節點然後標記這個節點對這個點連線的每一條邊進行鬆弛。因為每次都是找最小值,所以不能存在負權邊,因為存在負權邊會使路徑無限變小。

二、Floyd演算法  :

這種演算法可以找多源最短路,要想找到兩點間的最短路,只能通過找中間點,來縮短路徑,Floyd的演算法主題思想是動態規劃,核心程式碼只有五行,通過從1到n的遍歷找出每一箇中間點,查詢所有中間值,最終使得兩點間得距離達到最小。

演算法主體 :

for(int k=1; k<=n; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
if(map1[i][j]>map1[i][k]+map1[k][j])
map1[i][j]=map1[i][k]+map1[k][j];
}

實際運用中可以通過改變map陣列的含義來計算題目所需要的東西。

  • bellman-ford與SPFA演算法(帶負權的最短路問題) :

這種演算法可以計算負權值,一般用於有負權值的最短路,這個演算法也是通過遍歷n-1遍找過所有的點,因為最短路是一個不包含迴路的路徑,正負迴路都不能有,去掉迴路以後,n個點就只剩下了n-1條邊,但是這個迴圈有可能不到n-1次就找到了所有最短路,最壞的情況是n-1次迴圈。

演算法主體:

for(int k=1;k<=n-1;k++)//進行n-1次鬆弛
for(int i=1;i<=m;i++)//列舉每一條邊
if(dis[v[i]]>dis[u[i]]+w[i])//嘗試鬆弛每一條邊
dis[v[i]]=dis[u[i]]+w[i];

判斷負權迴路時只需要所有點鬆弛一遍後看能不能繼續鬆弛,如果還能鬆弛則代表存在負權迴路,正權會路只需改變一下就好。

  • spfa(佇列優化的bellman) :

Spfa是bellman的佇列優化形式。

以上就是我對最短路演算法的理解。