这道题目考查的就是对Folyd的灵活运用
因为这题是需要你去求多元最短路,所以用Dijkstra或SPFA的话,时间复杂度显然是不可以接收的。 当然了,如果你直接用Floyd的话,也是会超时的。所以这道题就需要我们掌握Floyd的原理,才可以解决掉。
那么,我们该怎么去做呢?
我们会发现,这道题目每个村庄修好的时间是不一致的,根据Floyd的思想,对于每一个新的查询时间t,我们只需要用在第k天修好的村庄去更新其它村庄的最短路即可。 在更新的过程中,我们会发现我们枚举的i,j两个点可能是尚未修复的,但这并没有关系,因为安照我们的算法思路,未被修复的村庄是不会被拿来更新其它村庄的距离的,而对于这两个村庄,我们只需要在读入时特判一下即可。 附一下代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define INF 1000000000
using namespace std;
int n,m,q,cnt,x,y,t,T,fi[300],head[300],map[300][300];
struct Edge{
int to,next,x;
}edge[100005];
void floyd(int k)
{
for(register int i = 1; i <= n; i++)
for(register int j = 1; j <= n; j++)
map[i][j] = min(map[i][j],map[i][k] + map[k][j]);
}
int main()
{
scanf(“%d%d”,&n,&m);
for(register int i = 1; i <= n; i++)
for(register int j = 1; j <= n; j++)
map[i][j] = INF;
for(register int i = 1; i <= n; i++) scanf(“%d”,&fi[i]);
for(register int i = 1; i <= m; i++)
{
scanf(“%d%d%d”,&x,&y,&t);
x ++; y ++; //个人习惯存的点的边号为1n,而题目给出的是0n-1
map[x][y] = t;
map[y][x] = t;
}
scanf(“%d”,&q);
T = 0;
for(register int a = 1; a <= q; a++)
{
scanf(“%d%d%d”,&x,&y,&t);
x ++; y ++;
while(t >= fi[T + 1] && T < n)
{
T++;
floyd(T);
}
if(fi[x] > t || fi[y] > t || map[x][y] == INF)
{
printf(“-1\n”);
continue ;
}
printf(“%d\n”,map[x][y]);
}
return 0;
}