开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情
题意:给出 B 地区的村庄数 N,村庄编号从 0 到 N−1,和所有 M 条公路的长度,公路是双向的。并给出第 i 个村庄重建完成的时间 ti,你可以认为是同时开始重建并在第 ti 天重建完成,并且在当天即可通车。若 ti 为 0 则说明地震未对此地区造成损坏,一开始就可以通车。之后有 Q 个询问(x,y,t),对于每个询问你要回答在第 t 天,从村庄 x 到村庄 y 的最短路径长度为多少。如果无法找到从 x 村庄到 y 村庄的路径,经过若干个已重建完成的村庄,或者村庄 x 或村庄 y 在第 t 天仍未重建完成,则需要返回 -1。
思路:
floyd三重循环的第一重是有意义的,是i和j之间允许那几个点作为中转点以使i和j的距离能够更短,那这题不就很好的体现了这个吗,那个村庄建好了,那个就被允许作为中转点了,然后进行一遍转移,之后在看看x,y之间有没有最短的路径就行了
#include<bits/stdc++.h>
//#pragma-GCC-optimize("-Ofast");
#define ll long long
//#define int long long
#define lowbit(x) ((x)&(-x))
#define endl '\n'
using namespace std;
const ll mod=998244353;
const ll inf=1e9;
const double pi=acos(-1);
const int N=1e6+100;
ll qpow(ll a,ll b)
{
ll res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
int n,m,t[205],g[205][205];
void floyd(int x){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=min(g[i][j],g[i][x]+g[x][j]);
}
signed main()
{
//ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>t[i];
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++){
g[i][j]=inf;
if(i==j) g[i][j]=0;
}
for(int i=1;i<=m;i++){
int u,v,w;cin>>u>>v>>w;
u++;v++;
g[u][v]=g[v][u]=w;
}
int q,cnt=1;cin>>q;
while(q--){
int x,y,ti;cin>>x>>y>>ti;
x++;y++;
while(t[cnt]<=ti&&cnt<=n){floyd(cnt);cnt++;}
if(g[x][y]==inf||t[x]>ti||t[y]>ti) cout<<"-1\n";
else cout<<g[x][y]<<endl;
}
return 0;
}