其他分享
首页 > 其他分享> > Luogu P5304 [GXOI/GZOI2019]旅行者

Luogu P5304 [GXOI/GZOI2019]旅行者

作者:互联网

题链

[P5304 GXOI/GZOI2019]旅行者 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

分析

首先显然求出所有的被标记的点出发的最短路

再建反图求出所有被标记的点出发的最短路

显然每个被标记的点都有自己的管辖范围(在管辖范围中的点距离该点最近)

假设最后答案是\((u,v)\),则显然对于\((u,v)\)最短路径上的点,都被\(u\)或\(v\)管辖(否则可以找到另外一对答案更小的点),且存在一个分界点使得分界点左边的点都归\(u\)管,右边的点都归\(v\)管,所以枚举分界边即可

#include<bits/stdc++.h>
#define ll long long
const ll INF=1e18;
using namespace std;

const int N=1e5+5;
int n,m,K,a[N];
struct B{int v; ll w;};
inline bool operator >(B i,B j) {
	return i.w>j.w;
}
priority_queue<B,vector<B>,greater<B> >Q;
struct A{
	vector<B>V[N];bool fl[N]; ll d[N]; int f[N]; 
	void clear() {
		for(int i=1;i<=n;i++) V[i].clear();
	}
	void dij() {
		for(int i=1;i<=n;i++) {
			fl[i]=0,d[i]=INF,f[i]=0;
		}
		for(int i=1;i<=K;i++) {
			f[a[i]]=a[i];
			Q.push((B){a[i],d[a[i]]=0});
		}
		while(!Q.empty()) {
			while(!Q.empty()&&fl[Q.top().v]) Q.pop();
			if(Q.empty()) break;
			int u=Q.top().v; fl[u]=1;
			for(B v:V[u]) {
				if(d[v.v]>d[u]+v.w) {
					f[v.v]=f[u];
					Q.push((B){v.v,d[v.v]=d[u]+v.w});
				}
			}
		}
	}
} tu1,tu2;
int main() {
	int T; scanf("%d",&T);
	while(T--) {
		scanf("%d%d%d",&n,&m,&K);
		tu1.clear(),tu2.clear();
		for(int i=1;i<=m;i++) {
			int u,v,k; scanf("%d%d%d",&u,&v,&k);
			tu1.V[u].push_back((B){v,k});
			tu2.V[v].push_back((B){u,k});
		}
		for(int i=1;i<=K;i++) {
			scanf("%d",&a[i]);
		}
		tu1.dij(); tu2.dij();
		ll ans=INF;
		for(int i=1;i<=n;i++) {
			for(B v:tu1.V[i]) {
				if(tu1.f[i]!=tu2.f[v.v]) ans=min(ans,tu1.d[i]+tu2.d[v.v]+v.w);
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

标签:标记,int,Luogu,ll,scanf,clear,GZOI2019,tu1,P5304
来源: https://www.cnblogs.com/wsfwsf/p/14718093.html