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