10.有边数限制的最短路 bellman-ford

 

 可以开一个结构体存储所有边

 这个更新的过程叫做松弛操作

bellman-ford算法循环完之后,所有边的距离一定满足

 这个叫三角不等式

在求最短路的时候,如果有负权回路的话,最短路是不一定存在的

bellman-ford算法可以求出来是不是有负权回路,负环,时间复杂度O(nm)

第一层for循环的循环次数是有实际意义的

比如说当前迭代了k次

那么我们求的最短距离的含义是:从1号点经过不超过k条边,走到每个点的最短距离

所以如果是第n次迭代的时候,又更新了某些边的话,就说明存在一条最短路径,这条最短路径上的边的个数是n。n条边就有n + 1个点,抽屉原理,一共有两个点一样,一定存在负环

但是一般找负环不用bellman-ford算法,时间复杂度太高,一般用spfa来做

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 510, M = 10010;
 4 struct edge{
 5   int a, b, w;  
 6 } edges[M]; //存所有边
 7 int n, m, k;
 8 int dist[N], backup[N];
 9 //备份
10 int bellman_ford() {
11     memset(dist, 0x3f, sizeof dist);
12     dist[1] = 0;
13     for (int i = 0; i < k; i++) { //迭代k次
14         memcpy(backup, dist, sizeof dist); //防串联
15         //只用上一次更新的结果来更新,防止串联
16         for (int j = 0; j < m; j++) {
17             int a = edges[j].a;
18             int b = edges[j].b;
19             int w = edges[j].w;
20             dist[b] = min(dist[b], backup[a] + w);
21         }
22     }
23     if (dist[n] > 0x3f3f3f3f / 2) { //见注解一,没还不太理解
24         return -1;
25     }
26     return dist[n];
27 }
28 int main() {
29     cin >> n >> m >> k;
30     for (int i = 0; i < m; i++) {
31         int a, b, w;
32         cin >> a >> b >> w;
33         edges[i].a = a;
34         edges[i].b = b;
35         edges[i].w = w;
36         //edges[i] = {a, b, w};
37     }
38     int t = bellman_ford();
39     if (t == -1) {
40         cout << "impossible" << endl;
41     } else {
42         cout << t << endl;
43     }
44     return 0;
45 }

注解一:

 比如1号点不能到5号点,1号点也不能到n号点,但是5号点可以到n号点

原文地址:https://www.cnblogs.com/fx1998/p/13334168.html