[图论]floyed最短路(灾后重建)
灾后重建
Description
B地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响。但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车。换句话说,只有连接着两个重建完成的村庄的公路才能通车,只能到达重建完成的村庄。
给出BB地区的村庄数NN,村庄编号从00到N-1N−1,和所有MM条公路的长度,公路是双向的。并给出第ii个村庄重建完成的时间t_iti,你可以认为是同时开始重建并在第t_iti天重建完成,并且在当天即可通车。若t_iti为00则说明地震未对此地区造成损坏,一开始就可以通车。之后有QQ个询问(x, y, t)(x,y,t),对于每个询问你要回答在第tt天,从村庄xx到村庄y的最短路径长度为多少。如果无法找到从xx村庄到yy村庄的路径,经过若干个已重建完成的村庄,或者村庄xx或村庄yy在第t天仍未重建完成 ,则需要返回-1−1。
Input
第一行包含两个正整数N,MN,M,表示了村庄的数目与公路的数量。
第二行包含NN个非负整数t_0, t_1,…, t_{N-1}t0,t1,…,tN−1,表示了每个村庄重建完成的时间,数据保证了t_0 ≤ t_1 ≤ … ≤ t_{N-1}t0≤t1≤…≤tN−1。
接下来MM行,每行33个非负整数i, j, wi,j,w,ww为不超过1000010000的正整数,表示了有一条连接村庄ii与村庄jj的道路,长度为ww,保证i≠ji≠j,且对于任意一对村庄只会存在一条道路。
接下来一行也就是M+3M+3行包含一个正整数QQ,表示QQ个询问。
接下来QQ行,每行33个非负整数x, y, tx,y,t,询问在第tt天,从村庄xx到村庄yy的最短路径长度为多少,数据保证了tt是不下降的。
output
共QQ行,对每一个询问(x, y, t)(x,y,t)输出对应的答案,即在第tt天,从村庄xx到村庄yy的最短路径长度为多少。如果在第t天无法找到从xx村庄到yy村庄的路径,经过若干个已重建完成的村庄,或者村庄x或村庄yy在第tt天仍未修复完成,则输出-1−1。
Examples
Input
4 5
1 2 3 4
0 2 1
2 3 1
3 1 2
2 1 4
0 3 5
4
2 0 2
0 1 2
0 1 3
0 1 4
Output
-1
-1
5
4
正确解法:
正解是floyed,因为数据量只有200
我刚开始想的是按边排序,然后按时间这样子一个个输入边,在floyed一边
成功的tle
后来看题解。只要把边全部输入就好了,然后看时间,如果时间到了就更新一遍。
加了一个特判。
哦我在想 提前输入边会不会对后面有影响。其实是没有影响的。
如果这个村庄没有的话,直接输出 -1 ,如果有的话,就可以直接floyed了
时间是单调递增的,这个先floyed了,后面只会在更新后面的点,对前面则没有影响。
1 #include "pch.h" 2 #pragma warning(disable:4996) 3 #include<iostream> 4 #include<cstdio> 5 #include<string> 6 #include<cstring> 7 #include<map> 8 #include<set> 9 #include<vector> 10 #include<queue> 11 #include<algorithm> 12 #include<cmath> 13 using namespace std; 14 typedef long long ll; 15 const int inf = 0x7fffffff; 16 const int N = 200 + 10; 17 const int M = 20000; 18 int n, m,q,now=0; 19 int xx, yy, tt; 20 int a[N][N],tim[N]; 21 void init() 22 { 23 scanf("%d %d",&n,&m); 24 for(int i=0;i<n;i++) 25 for (int j = 0; j < n; j++) 26 { 27 if (i == j) a[i][j] = 0; 28 else a[i][j] = inf; 29 } 30 for (int i = 0; i < n; i++) 31 scanf("%d",&tim[i]); 32 while (m--) 33 { 34 scanf("%d %d %d",&xx,&yy,&tt); 35 a[xx][yy] = tt; 36 a[yy][xx] = tt; 37 } 38 } 39 void floyed(int k) 40 { 41 for (int i = 0; i < n; i++) 42 for (int j = 0; j < n; j++) 43 if (a[i][k] != inf && a[k][j] != inf) 44 if (a[i][j] > a[i][k] + a[k][j]) 45 a[i][j] = a[i][k] + a[k][j]; 46 } 47 int main() 48 { 49 init(); 50 scanf("%d",&q); 51 while (q--) 52 { 53 scanf("%d %d %d",&xx,&yy,&tt); 54 while (tt >= tim[now] && now < n) 55 { 56 floyed(now); 57 now++; 58 } 59 if (tim[xx] > tt || tim[yy] > tt) 60 printf("-1\n"); 61 else 62 { 63 if (a[xx][yy] == inf) 64 printf("-1\n"); 65 else printf("%d\n", a[xx][yy]); 66 } 67 } 68 69 return 0; 70 }