题意:查询q次求一个村庄到另一个村庄的最短路,但这个题目又加了一个重建的条件,只有当一条路联通的两个村庄 (规定了村庄在第几天被修好) 都被修好这条路才可以通,所以点到点的最短距离又受制于时间t。
思路:查询是点到点在第t天的最短距离。首先这是多源最短路,各个村庄之间的最短距离我们都要知道,选用floyd食用最佳。接下来去解决时间t的问题。首先这个问题好的一点就是,村庄的重建好的时间是不下降的,查询的t也是不下降的,这样就very good了。floyd的第一层循环是枚举进行松弛的点。这里因为受制于t,所以我们接受一个查询,就将重建时间小于等于t的点都拿去松弛这一张图,但是因为查询的两个村庄可能还没有被重建,所以我们要判断一下,如果被重建过了而且被更新,那就输出最短距离,反之输出-1。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<cstring>
#include<algorithm>
#include<limits.h>
using namespace std;
typedef long long ll;
const ll INF=0x3f3f3f3f;
const ll inf=-0x3f3f3f3f;
const ll maxn=200+5;
int dist[maxn][maxn],t[maxn];
int n,m,q;
int main() {
scanf("%d%d",&n,&m);
memset(dist,0x3f,sizeof(dist));
for(int i=0; i<n; ++i) {
scanf("%d",t+i);
dist[i][i]=0;
}
int x,y,w;
for(int i=1; i<=m; ++i) {
scanf("%d%d%d",&x,&y,&w);
dist[x][y]=dist[y][x]=w;
}
scanf("%d",&q);
int xx,yy,tt,k=0;
for(int i=0; i<q; ++i) {
scanf("%d%d%d",&xx,&yy,&tt);
while(t[k]<=tt&&k<n) {
for(int i=0 ; i<n ; i++)
for(int j=0; j<n ;j++) {
dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
}
k++;
}
if(dist[xx][yy]==INF||t[xx]>tt||t[yy]>tt){
cout<<-1<<endl;
}
else cout<<dist[xx][yy]<<endl;
}
return 0;
}
一开始想用Dijkstra暴力出点到点的最小距离并用记忆化存储下来。但是就是不T也会MLE。但本菜鸡还是将其实现了出来,当然是“稻花香里说丰年,听取WA声一片”。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<cstring>
#include<algorithm>
#include<limits.h>
using namespace std;
typedef long long ll;
const ll INF=0x3f3f3f3f;
const ll inf=-0x3f3f3f3f;
const ll maxn=200+5;
ll n,m,q,maxday=-1;
int t[maxn];
struct node {
ll p;
ll dis;
node(ll np=0,ll ndis=0) {
p=np,dis=ndis;
}
bool operator <(const node& x)const {
return dis>x.dis;
}
};
struct edge {
ll id;
ll to;
ll w;
edge(ll nid=0,ll nto=0,ll nw=0) {
id=nid,to=nto,w=nw;
}
};
vector<edge> e[maxn];
int dist[maxn][maxn][10005];
// i->j 第t天的最短路
bool vis[maxn];
void Dijkstra(int start) {
for(int i=0; i<=n; ++i) {
for(int k=0; k<=t[n-1]+1; ++k) {
dist[start][i][k]=INF;
}
}
memset(vis, false, sizeof(vis));
dist[start][start][t[start]]=0;
priority_queue<node> q;
q.push(node(start,0));
while(!q.empty()) {
node tmp=q.top();
q.pop();
int np=tmp.p;
if(vis[np]) continue;
vis[np]=1;
for(int i=0; i<e[np].size(); ++i) {
edge ne=e[np][i];
ll nto=ne.to;
ll nw=ne.w;
ll nday=max(t[nto],t[np]);
if(dist[start][nto][nday]>dist[start][np][t[np]]+nw) {
dist[start][nto][nday]=dist[start][np][t[np]]+nw;
// cout<<start<<"->"<<nto<<" "<<nday<<" :"<<dist[start][nto][nday]<<endl;
q.push(node(nto,dist[start][nto][nday]));
}
}
}
bool flag=false;
for(int i=0; i<n; ++i) {
flag=false;
for(int k=0; k<=t[n-1]+1; ++k) {
if(dist[start][i][k]!=INF) {
flag=true;
} else {
if(flag) {
if(dist[start][i][k]==INF) {
dist[start][i][k]=dist[start][i][k-1];
}
}
}
}
}
}
int main() {
scanf("%lld%lld",&n,&m);
for(int i=0; i<n; ++i) {
scanf("%d",t+i);
}
ll x,y,w;
for(int i=1; i<=m; ++i) {
scanf("%lld%lld%lld",&x,&y,&w);//无向图建图
e[x].push_back(edge(i,y,w));
e[y].push_back(edge(i,x,w));
}
for(int i=0; i<n; ++i) {
Dijkstra(i);
}
scanf("%lld",&q);
int xx,yy,tt;
for(int i=0; i<q; ++i) {
scanf("%d%d%d",&xx,&yy,&tt);
if(dist[xx][yy][tt]==INF) {
cout<<-1<<endl;
} else {
cout<<dist[xx][yy][tt]<<endl;
}
}
return 0;
}