Bellman-Ford算法(最短路)

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次更新如果还有顶点更新最短路径,则说明存在负权回路;

猜你喜欢

转载自www.cnblogs.com/zdl2234/p/10356512.html