Bellman-Ford算法

Bellman-Ford算法的浅要理解

思路

一般被用于求经过不超过k条边的最短路问题(需要一个备份数组防止连锁松弛,即一次迭代中因一次松弛导致另一个松弛) 也可用于判负环(一般用spfa),n个点,第n次更新如果发生更新,那证明存在负权回路 创建一个dist数组和一个backup数组,通过k次迭代 (含义为经过不超过k条边的最短路),每一次迭代遍历所有边,进行松弛操作

1
dist[b] = min(dist[b] + backup[a] + w);

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <cstring>

using namespace std;

const int N = 510, M = 1e4 + 10;

int n, m, k;

int dist[N], backup[N];

struct node
{
int a, b, w;
} edge[M];

int bellman_ford()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for (int i = 0; i < k; i++)
{
memcpy(backup, dist, sizeof dist);
for (int j = 0; j < m; j++)
{
int a = edge[j].a, b = edge[j].b, w = edge[j].w;
dist[b] = min(dist[b], backup[a] + w);
}
}
if (dist[n] > 0x3f3f3f3f / 2) // 假如不存在路径 dist[n]仍可能被更新得小一些
return -1;
else
return dist[n];
}

int main()
{
scanf("%d%d%d", &n, &m, &k);
for (int i = 0; i < m; i++)
{
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
edge[i] = {x, y, z};
}
int t = bellman_ford();
if (t == -1)
puts("impossible");
else
printf("%d", t);
return 0;
}