[洛谷P1119]灾后重建

原题传送门

这道题是个好题,至少我第一下没有想到是一个古老的算法:$Floyd$

第一眼知道是个最短路,然后就很果断的写了$dijkstra$,对于每组输入求一遍最短路,发现时间很困难。又该写了$SPFA$。当时认为$SPFA$在新加入村庄时只需将其松弛操作即可。

后来发现超时,$80pts$。

事实上在维护新加入的村庄时计算最短路,$Floyd$在这方面很出色。$Floyd$满足三角不等式,即$i$到$j$借助新加入的村庄$k$进行维护,而且只需$O(n^2)$

综上,复杂度为$O(n^3)$。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 #define re register
 9 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
10 #define repd(i, a, b) for (re int i = a; i >= b; --i)
11 #define maxx(a, b) a = max(a, b);
12 #define minn(a, b) a = min(a, b);
13 #define LL long long
14 #define inf (1 << 30)
15 
16 inline int read() {
17     int w = 0, f = 1; char c = getchar();
18     while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();
19     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();
20     return w * f;
21 }
22 
23 const int maxn = 200 + 5;
24 
25 int dis[maxn][maxn], n, m, q, t[maxn];
26 
27 int main() {
28     memset(dis, 0x3f, sizeof(dis));
29 
30     n = read(), m = read();
31 
32     rep(i, 0, n-1) t[i] = read();
33     
34     rep(i, 1, m) {
35         int u = read(), v = read();
36         dis[u][v] = dis[v][u] = read();
37     }
38 
39     q = read();
40 
41     int k = 0;
42 
43     rep(kase, 1, q) {
44         int x = read(), y = read(), T = read();
45         while (k < n && T >= t[k]) {
46             rep(i, 0, n-1)
47                 rep(j, 0, n-1)
48                     if (i != k && j != k) minn(dis[i][j], dis[i][k] + dis[k][j]);
49             k++;
50         }
51         if (t[x] > T || t[y] > T || dis[x][y] == 1061109567) printf("-1\n");
52         else printf("%d\n", dis[x][y]);
53     }
54 
55     return 0;
56 }

 

posted @ 2019-01-25 20:05  AC-Evil  阅读(114)  评论(0编辑  收藏  举报