什么是bellman-ford算法?
bellman-ford算法是求含负权图的单源最短路径的一种算法,算法效率较低,代码难度较低。原理:假设1号点到n号点是可达的,每一个点同时向指定方向出发,更新相邻的点的距离,通过n-1(就是边数)次循环操作,如果图中不存在负环,则一定到达n点,如果存在负环,n-1次松弛后一定还会更新
具体步骤
for n次
for 所有边 a,b,w松弛操作
dist[b] = min(dist[b],backup[a] + w)
backup[]是备份数组,是为了防止串联而存在
题目链接:853. 有边数限制的最短路 - AcWing题库
c++代码实现+注释
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 510,M = 10010;
int n,m,k;
int dist[N],backup[N];
struct Edge{
int a,b,c;
}e[M];//结构体存边,用什么方式存边都可以
void bellman_ford()
{
memset(dist,0x3f,sizeof dist);
dist[1] = 0;
for(int i = 0; i < k; i ++ )//最多经过k条边,用k来限制边数(步数) (1)
{
memcpy(backup ,dist,sizeof dist);//备份,为什么需要备份,防止串联(2)
for(int j = 0; j < m; j ++ )//m条边
{
dist[e[j].b] = min(dist[e[j].b],backup[e[j].a] + e[j].c);
}
}
}
int main()
{
cin >> n >> m >> k;
for(int i = 0; i < m; i ++ )
{
int a,b,c;
cin >> a >> b >> c;
e[i] = {a,b,c};
}
bellman_ford();
if(dist[n] > 0x3f3f3f3f / 2) puts("impossible");//不写dist[n] == 0x3f3f3f3f的原因在于,有一种情况,起点到达不了n,但是n点被更新了,不再是这个数,所以只要大于和无穷大一个数量级的就可以认为到达不了
else cout << dist[n] <<endl;
return 0;
}
注释:2)串联:1->2->3(1->2距离为1 2->3距离为1 1->3距离为3) 边数限制为1
如果不加备份 初始: dist[1] = 0, dist[2] = 无穷 dist[3] = 无穷
第一次循环:dist[1] = 0,dist[2] = 1,dist[3] = 1,这就与每次一个点更新一条边,边数有限制背道而驰,,,加了备份以后,第一次循环时,dist[3] = 3