[洛谷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 }