noip模拟37 最小距离

多源最短路

顾名思义,我们开始有多个源头,然后跑最短路。
其中的 \(dis\) 数组记录的是该点到任意源点的最短距离。


然后这道题就迎刃而解了,我们枚举路径,
对于路的端点找 \(pre\) 数组,对答案取 \(min\) 即可。

code:

#include <bits/stdc++.h>
#define re register
#define int long long
#define pir make_pair
using namespace std; 
const int maxn=200010;
const int INF=1e15;
inline int read() {
    int s=0,w=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') w=-1;ch=getchar(); }
    while(ch>='0'&&ch<='9') { s=s*10+ch-'0'; ch=getchar(); }
    return s*w; 
} 

int n,m,p;
struct EDGE { int var,cst,nxt; } edge[maxn<<1];
int head[maxn],cnt;
struct DATE { int a,b,w; } dat[maxn];
inline void add(int a,int b,int c) { edge[++cnt]=(EDGE){b,c,head[a]}; head[a]=cnt; }
int dis[maxn],pre[maxn],sl[maxn]; bool vis[maxn],z[maxn];
priority_queue< pair<int,int> >q; 
inline void spfa() {
	while(!q.empty()) {
		int x=q.top().second; vis[x]=0; q.pop(); 
		for(re int i=head[x],to;~i;i=edge[i].nxt) {
			to=edge[i].var;
			if(dis[to]>dis[x]+edge[i].cst) {
				dis[to]=dis[x]+edge[i].cst;
				pre[to]=pre[x];
				if(!vis[to]) { 
					q.push(pir(-dis[to],to)); 
					vis[to]=1; 
				}
			}
		}
	}
}
int ansl[maxn];
signed main() {
	//freopen("distance.in","r",stdin);
	n=read(),m=read(),p=read();
	memset(dis,0x3f,sizeof(dis));
	for(re int i=1;i<=p;i++) { 
		sl[i]=read(); 
		q.push(pir(0,sl[i])); 
		dis[sl[i]]=0; vis[sl[i]]=1; 
		pre[sl[i]]=sl[i]; z[sl[i]]=1;
	}
	memset(head,-1,sizeof(head));
	for(re int i=1;i<=m;i++) { 
		dat[i].a=read(),dat[i].b=read(),dat[i].w=read();
		add(dat[i].a,dat[i].b,dat[i].w); 
		add(dat[i].b,dat[i].a,dat[i].w); 
	}
	spfa();
	for(re int i=1;i<=p;i++) ansl[sl[i]]=INF;
	for(re int i=1,a,b,u,v;i<=m;i++) {
		u=dat[i].a; v=dat[i].b;
		a=pre[u]; b=pre[v];
		if(a==b) continue;
		ansl[a]=min(ansl[a],dis[u]+dis[v]+dat[i].w);
		ansl[b]=min(ansl[b],dis[u]+dis[v]+dat[i].w);
	}
	for(re int i=1;i<=p;i++) { printf("%lld ",ansl[sl[i]]); }
}
posted @ 2021-08-12 20:30  zJx-Lm  阅读(37)  评论(0编辑  收藏  举报