【Bellman-Ford】

【Bellman-Ford】

最短路算法

https://www.acwing.com/problem/content/855/
※求带有负权边的最短路
※若限制只能经过k条边->只能用Bellman-Ford
时间复杂度:\(O(nm)\)

※若图带有负环->不一定有最短路

无最短路
image
有最短路
image

思路

//不用邻接表存图->只存边信息
for n次
	for 所有边 a b w (松弛操作)
		dist[b]=min(dist[b],dist[a]+w)

//三角不等式
dist[b]<=dist[a]+w

代码

※注意
(1)每次更新都只使用上一次迭代的结果:dist数组要备份
(2)考虑到(无穷大-负权边):判断不存在结果时 只需要大于一个很大的数就行(0x3f3f3f33f/2)

#include<bits/stdc++.h>
using namespace std;
const int N=510,M=10010;
struct Edge{
	int a,b,w;
}edge[M];//存边 
int n,m,k;
int dist[N];
int last[N];//只能在上一次迭代的结果下操作->需要备份 
void bellman_ford(){
	memset(dist,0x3f,sizeof dist);
	dist[1]=0;
	for(int i=0;i<k;i++){
		//备份
		memcpy(last,dist,sizeof dist);
		for(int j=0;j<m;j++){
			auto e=edge[j];
			                       //用上一次的数据来计算 
			dist[e.b]=min(dist[e.b],last[e.a]+e.w);
		}
	}
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=0;i<m;i++){
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		edge[i]={a,b,c};
	}
	bellman_ford();
	//注意这里:大于一个很大的数就行 不能是无穷大(存在无穷大-负权边) 
	if(dist[n]>0x3f3f3f3f/2) printf("impossible");
	else printf("%d",dist[n]);
	return 0;
}
posted @ 2025-01-08 13:03  White_ink  阅读(31)  评论(0)    收藏  举报