Floyd-任意两点间最短路
复杂度: O(v^3)
思想: DP 通过枚举中间点来优化它的时间复杂度
d[i][j][k]表示从i到j在节点只允许经过[0,k]时的最短距离
a. 如果最短路经过k点,则d[i][j][ k ] = d[i][k][k-1] + d[k][j][k-1]
b. 如果最短路不经过k点,则d[i][j][k] = d[i][j][k-1]
于是有状态转移方程: d[i][j][k] = min{ d[i][j][k-1], d[i][k][k-1] + d[k][j][k-1] }
一般省去后面一维,变为二维:d[i][j] = min{d[i][j], d[i][k] + d[k][j]}
核心代码
for(int k = 0; k < n; k++)//k是中转节点,跳板
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if(a[i][j] > a[i][k]+a[k][j])
a[i][j] = a[i][k]+a[k][j];
不懂的可以照着题目边写边理解
例题 hdu1874畅通工程续
当然了这题没必要用floyd,但是我们可以利用floyd来解决
不过这题有点坑:1.重边的处理2.起点与终点相同的情况注意一下就好了
31ms 1484k
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #include <cmath>
6 using namespace std;
7
8 #define mem(a) memset(a,0,sizeof(a))
9 #define ll long long
10 const int maxn = 300;
11 const int inf = 0x3f3f3f3f;
12 int a[maxn][maxn];
13
14 int main()
15 {
16 int n,m,u,v,w;
17 while(~scanf("%d",&n))
18 {
19 scanf("%d",&m);
20 for(int i = 0; i < n; i++)
21 for(int j = 0; j < n; j++)
22 a[i][j] = (i==j?0:inf);
23 for(int i = 0; i < m; i++)
24 {
25 scanf("%d%d%d",&u,&v,&w);
26 if(w < a[u][v])
27 a[u][v] = a[v][u] = w;
28 }
29 for(int k = 0; k < n; k++)
30 for(int i = 0; i < n; i++)
31 for(int j = 0; j < n; j++)
32 if(a[i][j] > a[i][k]+a[k][j])
33 a[i][j] = a[i][k]+a[k][j];
34 int x,y;
35 scanf("%d%d",&x,&y);
36 if(a[x][y] == inf)
37 printf("-1\n");
38 else
39 printf("%d\n",a[x][y]);
40 }
41 return 0;
42 }
附这题的Dijkstra算法