洛谷 1119 灾后重建 Floyd

  比较有趣的Floyd,刚开始还真没看出来。。。。(下午脑子不太清醒)


  先考虑一下Floyd本身的实现原理,

  1. for(k=1;k<=n;k++)   
  2. for(i=1;i<=n;i++)  
  3. for(j=1;j<=n;j++)   
  4. if(e[i][j]>e[i][k]+e[k][j])   
  5. e[i][j]=e[i][k]+e[k][j]

  枚举图中的每一个点,用这些点去逐次更新当前的图,最终得到的dis值就是最终的每两点的最小距离


 

  没有学过Floyd的同学可以参考啊哈磊的Floyd讲解


  那么对于这道题目,我们就可以直接按照每个点修好的时间排序,按照该顺序加入点,进行Floyd,输出dis值即为结果

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 const int maxn = 500;
 6 const int inf = 0x3f3f3f3f >> 1;
 7 int dis[maxn][maxn];
 8 int pointTime[maxn];
 9 int askx[50500], asky[50500], askt[50500];
10 int n, m;
11 int tot = 0;
12 int x, y, z;
13 int q;
14 int cur = 0;
15 
16 void update(int x) {
17     for (int i = 0; i < n; i++)
18         for (int j = 0; j < n; j++) {
19             dis[i][j] = std :: min(dis[i][j], dis[i][x] + dis[x][j]);
20         }
21 }
22 
23 int main () {
24     scanf("%d %d", &n, &m);
25     for (int i = 0; i < n; i++) 
26         scanf("%d", &pointTime[i]);
27     for (int i = 0; i < n; i++) 
28         for (int j = 0; j < n; j++) {
29             if (i == j) dis[i][j] = 0;
30             else dis[i][j] = inf;
31         }
32     for (int i = 1; i <= m; i++) {
33         scanf("%d %d %d", &x, &y, &z);
34         dis[x][y] = z;
35         dis[y][x] = z;
36     }
37     scanf("%d", &q);
38     for (int i = 1; i <= q; i++) {
39         scanf("%d %d %d", &askx[i], &asky[i], &askt[i]);
40         while (pointTime[cur] <= askt[i] && cur < n) {
41             update(cur);
42             cur++;
43         }
44         if (dis[askx[i]][asky[i]] >= inf || pointTime[askx[i]] > askt[i] || pointTime[asky[i]] > askt[i]) printf("-1
");
45         else printf("%d
", dis[askx[i]][asky[i]]);
46     }
47     
48     
49     return 0;
50 }

 

原文地址:https://www.cnblogs.com/CtsNevermore/p/6039405.html