Bellman-Ford算法(最短路)
阿新 • • 發佈:2019-02-08
ios 檢查 name 時間復雜度 bre end spa string 所有
Bellman-Ford算法是通過每一條邊對除源點外的其他頂點最短路更新,求得最短路徑;Bellman-Ford算法可以解決負邊權問題;
存邊:把圖的每一條邊存在u[i] , v[i] , w[i] 中,第i條邊表示從頂點u[i]到頂點v[i],邊權為w[i]的一條邊;
核心算法:
for(int k=1;k<n;k++){//n-1輪更新最短路徑,因為任何一定的最短路徑不會超過n-1條邊 for(int i=i;i<=m;i++){//每一輪枚舉所有邊,更新邊的終點的最短路徑 if(dis[v[i]]>dis[u[i]]+w[i])//如果通過這條邊,路徑變短 dis[v[i]]=dis[u[i]]+w[i];//更新最短路徑 } }
所以Bellman-Ford算法的時間復雜度為O(nm)
完整代碼
#include <string.h> #include<iostream> #define _Max 200010 #define INF 100000000 using namespace std; int v[_Max],u[_Max],w[_Max]; int dp[20010]; int main() { int n,m; cin>>n>>m; for(int i=0;i<m;i++){ cin>>u[i]>>v[i]>>w[i]; } for(int i=2;i<=n;i++){//其他點最短路徑初始為無窮大 dp[i]=INF; } dp[1]=0;//源點最短路徑初始為零 for(int j=0;j<n;j++){ for(int i=0;i<m;i++){ if(dp[v[i]]>dp[u[i]]+w[i]) dp[v[i]]=dp[u[i]]+w[i]; } } for(inti=2;i<=n;i++){ cout<<dp[i]<<endl; } return 0; }
優化:
1. Bellman-Ford算法最多更新n-1次就可以得到所有點的最短路徑,但有時候可能不需要n-1次就已經獲得所有點最短路徑;其實如果枚舉一次所有邊,沒有點更新最短路徑,則說明所有點都已取得最短路徑,則可以結束循環;
for(int k=1;k<n;k++){//n-1輪更新最短路徑,因為任何一定的最短路徑不會超過n-1條邊 check=1; for(int i=i;i<=m;i++){//每一輪枚舉所有邊,更新邊的終點的最短路徑 if(dis[v[i]]>dis[u[i]]+w[i]){//如果通過這條邊,路徑變短 dis[v[i]]=dis[u[i]]+w[i];//更新最短路徑 check=0; } } if(check==1) break; //如果check等於一,則說明沒有更新過最短路徑,則可以結束循環 }
擴展:
檢查負權回路:因為n-1次更新就可以獲得所有頂點的最短路徑,所以第n次更新如果還有頂點更新最短路徑,則說明存在負權回路;
Bellman-Ford算法(最短路)