noip模擬37 最小距離
阿新 • • 發佈:2021-08-12
多源最短路
顧名思義,我們開始有多個源頭,然後跑最短路。
其中的 \(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]]); } }