题目链接:
P1119 灾后重建
离noip还有54天然而蒟蒻的我连洛谷的试炼场都没有刷完(我太弱了)于是开始刷题。之后就刷到了这道题。
这是一道最短路的经典题,题目自己打开链接看好吧,我就不粘贴了谢谢(才不是因为我懒)。
对于这道题数组最好从
0
0
0开始,因为村庄数是从
0
0
0开始的。
这个题要询问是否两点是否联通(是否修好路了)和最短路。
由于道路在不断的修好所以不同时间的最短路也可能不同,所以要做N遍Floyed。
因为这道题的维修时间已经排好序了,所以不用排序如果没拍好,还要排一边序。
定义一个中转点K,让K从第一个点开始枚举如果修好了就可以以K为中转点跑Floyed。
#include<cstdio>
#include<iostream>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
inline int read( )
{
int x = 0; char c = getchar( );
while(!isdigit(c)) c = getchar( );
while(isdigit(c)) x = (x<<1) + (x<<3) + (c^48) , c = getchar();
return x;
}
int n,m,q,map[205][205];
int main( )
{
memset(map, 0x3f3f3f3f, sizeof(map));
n = read( );
m = read( );
int t[n];
for(int i = 0; i < n; i++)
{
t[i] = read( );
map[i][i] = 0;
}
for(int i = 1; i <= m; i++)
{
int a,b,c;
a = read( );
b = read( );
c = read( );
map[b][a] = map[a][b] = c;
}
int k = 0;
q = read( );
for(int p = 1; p <= q; p++)
{
int z,y,t1;
z = read( );
y = read( );
t1 = read( );
if(t[z] > t1 ||t[y] > t1)
{
printf("-1\n");
continue;
}
while(t[k] <= t1)
{
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
map[i][j] = min(map[i][j], map[i][k] + map[k][j]);
k++;
}
if(map[z][y] == 0x3f3f3f3f)
printf("-1\n");
else
printf("%d\n",map[z][y]);
}
return 0;
}