欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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;
}

推荐阅读