貝爾曼 福特最短路演算法及其優化(SPFA)

2021-09-26 06:43:20 字數 1934 閱讀 9729

日常膜拜dalao:財神萬歲!!!!!!!!!!!!!!!!!!!!!!!

日常凌晨水題解。。。(我發誓這是我今天最後一篇部落格了。。)

話說,,我的部落格一般解釋全在**注釋裡面,,而且講的不細緻。真的想詳細看模擬的話參見dalao的部落格:

為什麼我們不用dijkstra演算法?

因為,dijkstra無法處理負權邊的狀況(這個我這篇部落格不細講)。而貝爾曼—福特演算法可以很優秀的解決這個問題;(而且貝爾曼福特很好理解)

用dis陣列來表示每個點到原點的距離,w 陣列來表示每條邊的權值,u陣列表示每條邊的起點,v陣列表示每條邊的終點。

貝爾曼-福特演算法的主要思想是用邊來進行更新,將所有的點迴圈一遍,再將所有的邊迴圈一遍,每次看是否能用邊成功的將乙個點的距離更新(初始除了原點每個點的dis都是inf)

當存在負權迴路時,兩層迴圈完後仍然有點能夠被更新。

話不多說,上**:

#include

//貝爾曼—福特(bellman_ford)

#define inf 0x3f3f3f

using namespace std;

/*此演算法的思想:用邊來進行更新,進行n-1次迴圈,每次列舉一條邊,

如果這條邊的dis[v]>dis[u]+w[i]則對其進行更新,兩層迴圈完後,

如果還有能更新臨點的邊,則存在負權迴路 */

int m,n;

int dis[

100000];

int u[

2000

],v[

2000

],w[

2000];

void

belman

(int s)

//s是源點

} flag=false;

for(

int i=

1;i<=m;i++

)//若有點兩重迴圈完了以後還能夠被更新,

}int

main()

belman(1

);}

然而,貝爾曼福特演算法的複雜度比迪傑斯特拉還要差,o(n*m)。

所以就有了通過佇列對貝爾曼福特進行優化的spfa演算法

利用佇列存放被更新的點,顯而易見,只有乙個被更新過的點才能被用來更新其他的點(原點除外),將被更新的點扔到佇列裡面,每次取出隊首的點看是否能夠用來更新其臨點,注意:與廣度優先搜尋不同的是,乙個點可能入隊很多次,佇列空了演算法結束。

本**使用了stl佇列,如果不懂stl,手寫佇列也可以

#include

#include

#include

#define maxn 1005

#define maxm 2005

#define inf 0x3f3f3f

/*利用佇列對福特演算法進行優化,將被更新的點放到佇列種,

每次取出佇列前面的點並對其臨點進行更新,若被更新則可用來再次

更新其臨點,與廣搜不同的是,乙個點可能入隊很多次。當佇列空了,

演算法結束。*/

using namespace std;

struct node

ed[maxm]

; queue<

int> p;

int head[maxn]

,inque[maxn]

,dis[maxn]

;int m,n,cnt=0;

void

addnode

(int u,

int v,

int w)

void

spfa

(int s)}}

}}intmain()

memset

(inque,0,

sizeof

(inque));

spfa(1

);return0;

}

貝爾曼最短路徑演算法

時間複雜度為o n n 比dijkstra演算法慢,但是能夠檢查負圈 include include include include include include include include const int max 1e5 10 const int inf 1e6 using namesp...

Bellman Ford貝爾曼福特演算法實現

作為一種單源最短路徑演算法,bellman ford對於有向圖和無向圖都能適用,它還有乙個 dijkstra演算法無法 具備的特點,那就是對含負權圖的最短路徑搜尋。每i輪對邊的遍歷之後,只要不存在負權迴路,bellman ford演算法都 可以保證獲得距離源點i條邊的點的最短路徑。因為最短路徑的最大...

最短路之dijkstra及其堆優化

dijkstra演算法用來解決單源最短路徑問題 通常來說就是求解乙個圖中兩節點的最短路徑 只適用於正權邊 該演算法的樸素想法是鬆弛的思想 即若dis 1 3 7 dis 1 2 1 dis 2 3 1 則節點2的存在就可以對1,3鬆弛 在鬆弛完乙個節點之後要選擇尚未進行鬆弛的節點鬆弛,且要選擇距起點...