題解 最小距離
阿新 • • 發佈:2021-08-12
考試時思路是從每個點BFS,浸染當前與它最近的點,但複雜度有點假
其實這個過程可以一次dijkstra完成,利用多源最短路
每個特殊點都是一個源點,擴充套件時記錄一下是從哪個源點擴充套件過來的
統計答案時列舉所有兩端點不是由同一源點擴充套件的邊即可
挺好的題,可惜沒想出來
Code:
#include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define N 200010 #define ll long long #define fir first #define sec second #define make make_pair //#define int long long char buf[1<<21], *p1=buf, *p2=buf; #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++) inline int read() { int ans=0, f=1; char c=getchar(); while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();} while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();} return ans*f; } int n, m, p; int x[N], head[N], size=1, back[N]; bool vis[N]; ll dis[N], ans[N]; struct edge{int from, to, next; ll val;}e[N<<1]; inline void add(int s, int t, ll w) {e[++size].to=t; e[size].from=s; e[size].val=w; e[size].next=head[s]; head[s]=size;} struct cmp{inline bool operator () (pair<ll, int> a, pair<ll, int> b) {return a.fir>b.fir;}}; void dijkstra() { memset(dis, 127, sizeof(dis)); priority_queue< pair<ll, int> , vector< pair<ll, int> >, cmp> q; for (int i=1; i<=p; ++i) dis[x[i]]=0, back[x[i]]=x[i], q.push(make(0, x[i])); while (q.size()) { int t=q.top().sec; q.pop(); //cout<<"t: "<<t<<' '<<dis[t]<<endl; if (vis[t]) continue; vis[t]=1; for (int i=head[t],v; ~i; i=e[i].next) { v = e[i].to; if (vis[v]) continue; if (dis[v] > dis[t]+e[i].val) { dis[v]=dis[t]+e[i].val; back[v]=back[t]; q.push(make(dis[v], v)); } } } } signed main() { memset(head, -1, sizeof(head)); memset(ans, 127, sizeof(ans)); n=read(); m=read(); p=read(); for (int i=1; i<=p; ++i) x[i]=read(); for (int i=1,u,v,w; i<=m; ++i) { u=read(); v=read(); w=read(); add(u, v, w); add(v, u, w); } dijkstra(); ll t; for (int i=2; i<=size; ++i) if (i&1 && back[e[i].from]!=back[e[i].to]) { //cout<<"diff "<<back[e[i].from]<<' '<<back[e[i].to]<<endl; t = dis[e[i].from]+dis[e[i].to]+e[i].val; ans[back[e[i].from]]=min(ans[back[e[i].from]], t); ans[back[e[i].to]]=min(ans[back[e[i].to]], t); } for (int i=1; i<=p; ++i) printf("%lld ", ans[x[i]]); printf("\n"); return 0; }