Bellman-Ford——解决负权边(求某点到所有点的最短距离)

Bellman-Ford与dijkstra一样 都是求某点到所有点的最短距离

先说一下Bellman-Ford的思路:将m条变全部枚举(假设第i条边连接的点是u[i].v[i])判断v[i]到起点的距离是否可以通过v[i]到u[i]的距离和u[i]到起点的距离和替换从而更新dis[v[i]],显然,第一次循环一定会将离起点最近的点更新至最小,第二次循环又会将除起点外离离起点最近的点最近的点(有点绕,多看几遍)更新,以此类推,最多循环n-1次就能将所有dis更新。当然也有可能,一次循环就更新了所有的dis至最小值,这个待会再考虑。(这种更新称为“松弛”)

核心代码:

for(k=1;k<=n-1;k++){
	for(i=1;i<=m;i++){
		if(dis[v[i]]>dis[u[i]]+w[i]){
			dis[v[i]]=dis[u[i]]+w[i];
		}
	}
}


完整代码:

#include<cstdio>
using namespace std;
int main(){
	int i,j,k,m,n,u[10],v[10],w[10],dis[10];
	const int inf=99999999;
	scanf("%d %d",&n,&m);
	for(i=1;i<=m;i++){
		scanf("%d %d %d",&u[i],&v[i],&w[i]);
	}
	for(i=1;i<=n;i++){
		dis[i]=inf;
	}
	dis[1]=0;
	for(k=1;k<n;k++){
		for(i=1;i<=m;i++){
			if(dis[v[i]]>dis[u[i]]+w[i]){
				dis[v[i]]=dis[u[i]]+w[i];
			}
		}
	}
	for(i=1;i<=n;i++){
		printf("%d ",dis[i]);
	}
	return 0;
}
显然算法复杂度是O(NM)。
之前也说过,有可能不需要n-1轮就已经更新完毕,所以我们需要一个判断变量,判断每一轮松弛,如果m条边都没有更新dis,那么说明更新完毕,直接break;

另外,Bellman-Ford显然可以判断有没有负权环,之前已经分析过,最多n-1轮,就可以将所有的dis更新至最小,若第n轮还能继续更新,说明存在负权环。

核心代码:

for(k=1;k<=n-1;k++){
	for(i=1;i<=m;i++){
		if(dis[v[i]]>dis[u[i]]+w[i]){
			dis[v[i]]=dis[u[i]]+w[i];
		}
	}
}//更新 
flag=0;
for(i=1;i<=m;i++){
	if(dis[v[i]]>dis[u[i]]+w[i]){
		flag=1;
		break;
	}
}
if(flag==1)printf("有负权环");//判断负权环 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值