1. 程式人生 > >Bellman-Ford算法(最短路)

Bellman-Ford算法(最短路)

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(int
i=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算法(最短路)