Bellman-Ford算法(最短路)
Posted zdl2234
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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次更新如果还有顶点更新最短路径,则说明存在负权回路;
以上是关于Bellman-Ford算法(最短路)的主要内容,如果未能解决你的问题,请参考以下文章