Interplanetary
程序员文章站
2022-05-27 20:06:12
...
题目链接:Interplanetary
显然询问具有单调性,所以我们可以离线来做。
把点的温度排序。
然后就变成每次增加一个点,然后快速更新任意两点之间的最短路,因为n很小,所以直接floyd即可。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=410,M=1e5+10;
const int inf=0x3f3f3f3f;
int n,m,q,T[N],g[N][N],id[N],v[N][N],res[M],tmp[N][N];
struct node{int u,v,lim,id;};
vector<node> q1,q2; vector<int> vec;
inline void add(int now){
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
g[i][j]=min(g[i][j],g[i][now]+g[now][j]);
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) v[i][j]=g[i][j]=(i==j?0:inf);
for(int i=1;i<=n;i++) cin>>T[i],id[i]=i,vec.push_back(T[i]);
for(int i=1,a,b,c;i<=m;i++) scanf("%d %d %d",&a,&b,&c),v[a][b]=v[b][a]=min(v[a][b],c);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) g[i][j]=v[i][j];
cin>>q; sort(vec.begin(),vec.end()); vec.erase(unique(vec.begin(),vec.end()),vec.end());
for(int i=1,a,b,c,d;i<=q;i++){
scanf("%d %d %d %d",&a,&b,&c,&d);
if(d) q2.push_back({a,b,c,i});
else q1.push_back({a,b,c,i});
}
sort(q1.begin(),q1.end(),[](node a,node b){
return a.lim<b.lim;
});
sort(id+1,id+1+n,[](int a,int b){
return T[a]<T[b];
});
int pos=1;
for(node i:q1){
while(pos<=n&&T[id[pos]]<=vec[i.lim-1]) add(id[pos]),pos++;
res[i.id]=g[i.u][i.v];
}
sort(q2.begin(),q2.end(),[](node a,node b){
return a.lim<b.lim;
});
sort(id+1,id+1+n,[](int a,int b){
return T[a]>T[b];
});
pos=1; reverse(vec.begin(),vec.end());
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) g[i][j]=v[i][j];
for(node i:q2){
while(pos<=n&&T[id[pos]]>=vec[i.lim-1]) add(id[pos]),pos++;
res[i.id]=g[i.u][i.v];
}
for(int i=1;i<=q;i++)
if(res[i]==inf) puts("-1");
else printf("%d\n",res[i]);
return 0;
}
推荐阅读