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

 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 }
Floyd

 附这题的Dijkstra算法

posted on 2019-08-17 09:41  By_布衣  阅读(163)  评论(0编辑  收藏  举报

导航