洛谷 P1119 灾后重建(Floyd)
嗯...
题目链接:https://www.luogu.org/problem/P1119
这道题是一个Floyd的很好的题目,在Floyd的基础上加一点优化:
中转点k在这里不能暴力枚举,否则会超时,我们则可以用时间的限制来优化一下,用一个while,只有中转站被修复(即中转站修复时间小于t)时,k才能作为中转站,也就是指枚举在t时,被修复了的中转站,这样时间复杂度会降低一些...
本题细节问题:
1.每个村庄的下标是从0开始的
2.因为memset比较神奇,所以最后判-1时,要找一个比0x3f的数大的数进行判断,并且是>=
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 5 using namespace std; 6 7 int g[205][205], a[20005], n, m; 8 9 inline void update(int k){ 10 for(int i = 0; i < n; i++){ 11 for(int j = 0; j < n; j++){ 12 g[i][j] = min(g[i][j], g[i][k] + g[k][j]); 13 } 14 } 15 return; 16 } 17 18 int main(){ 19 memset(g, 0x3f, sizeof(g)); 20 scanf("%d%d", &n, &m); 21 for(int i = 0; i < n; i++) {scanf("%d", &a[i]); g[i][i] = 0;}//枚举细节 22 for(int i = 1; i <= m; i++) { 23 int x, y, z; 24 scanf("%d%d%d", &x, &y, &z); 25 g[x][y] = g[y][x] = z; 26 } 27 int q, now = 0; 28 scanf("%d", &q); 29 for(int i = 1; i <= q; i++) { 30 int u, v, t; 31 scanf("%d%d%d", &u, &v, &t); 32 while(a[now] <= t && now < n){ 33 update(now); 34 now++; 35 } 36 if(g[u][v] >= 0x3f3f3f3f || a[u] > t || a[v] > t) printf("-1\n"); 37 else printf("%d\n", g[u][v]); 38 } 39 return 0; 40 }