Bellman-Ford
算法思路
对图中每条边进行松弛操作,依此遍历每条边,遍历完成即可得出最短距离
注意事项
bellman-ford算法可以判断负环。
注意代码中backup数组的使用,防止串联。
主要适用于有判断次数的题目
例题
给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数。
请你求出从1号点到n号点的最多经过k条边的最短距离,如果无法从1号点走到n号点,输出impossible。
注意:图中可能 存在负权回路 。
输入格式
第一行包含三个整数n,m,k。
接下来m行,每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。
输出格式
输出一个整数,表示从1号点到n号点的最多经过k条边的最短距离。
如果不存在满足条件的路径,则输出“impossible”。
数据范围
1≤n,k≤500,
1≤m≤10000,
任意边长的绝对值不超过10000。
输入样例:
3 3 1
1 2 1
2 3 1
1 3 3
输出样例:
3
#include<bits/stdc++.h>
using namespace std;
const int N = 10010;
int n,m,k;
int dist[N],backup[N];
struct zzz{
int x;
int y;
int w;
}z[N];
int bellman_ford(){
memset(dist,0x3f,sizeof dist);
dist[1]=0;
for(int i=0;i<k;i++){
memcpy(backup,dist,sizeof dist); //防止串联,保证每次判断的时候下一个状态
//只能从上一个状态推出,如题目样例,若不进行备份操作,则下面的循环一次就会将dist[3]更新为2,
//但答案是3,因为造成了串联,再智能判断一条边的情况下无法对顶点3进行松弛操作。
for(int j=1;j<=m;j++){
int a=z[j].x;
int b=z[j].y;
int w=z[j].w;
if(dist[b]>backup[a]+w){
dist[b]=backup[a]+w;
}
}
}
if(dist[n]>0x3f3f3f3f/2) return -1;
return dist[n];
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=m;i++){
cin>>z[i].x>>z[i].y>>z[i].w;
}
int t=bellman_ford();
if(t==-1) cout<<"impossible"<<endl;
else cout<<t<<endl;
return 0;
}