1. 程式人生 > >牛客國慶集訓派對Day3 I Metropolis(多源多匯最短路)

牛客國慶集訓派對Day3 I Metropolis(多源多匯最短路)

題意:pp個點mm條無向邊,對於這pp個點,問距離其它點最近的距離。

題解:首先,如果我們考慮最暴力的方法,pp次單源最短路。但是pp的大小有2e52e5,明顯是不可能了。那就考慮多源最短路吧。將這pp個點都加入佇列作為源點。對於每一個節點,我們記錄它是由哪一個源點擴展出來的。當從一個源點ii,擴充套件到另一個源點jj擴展出來的一個節點uu時,那麼dis(i,j)=min(dis(i,j),dis[u]+dis[v]+w)dis(i,j) = min(dis(i,j),dis[u]+dis[v]+w)

+w) 在這裡插入圖片描述 就不需要再繼續擴充套件了。具體看程式碼叭~

程式碼

#include<bits/stdc++.h>

typedef long long LL;
#define P pair<LL,LL>
using namespace std;
const int N = 2e5+10;
const LL inf = 1e17;
int n,m,p,metrp[N],from[N];

struct node{
	LL v,w;
};
LL dis[N],ans[N];
vector<node> e[N];
priority_queue<P, vector<
P>, greater<P> > pq; void dijkstra() { memset(dis,0x3f,sizeof dis); for(int i = 0; i < p; ++i) pq.push(P(dis[metrp[i]] = 0, metrp[i])); while(!pq.empty()){ P cur = pq.top(); pq.pop(); LL cost = cur.first; LL u = cur.second; if(dis[u] < cost) continue; int len = e[u].size
(); for(int i = 0; i < len; ++i){ LL v = e[u][i].v; LL w = e[u][i].w; if(dis[u] + w < dis[v]){ dis[v] = dis[u] + w; from[v] = from[u]; pq.push(P(dis[v],v)); }else if(from[u] != from[v]){ ans[from[u]] = min(ans[from[u]],dis[u] + dis[v] + w); ans[from[v]] = min(ans[from[v]],dis[u] + dis[v] + w); } } } } void solve() { dijkstra(); for(int i = 0; i < p; ++i) printf("%lld%c",ans[metrp[i]],i == p - 1 ? '\n' : ' '); } int main() { #ifndef ONLINE_JUDGE freopen("input.in","r",stdin); #endif cin>>n>>m>>p; int u,v,w; for(int i = 0; i < p; ++i){ cin>>metrp[i]; ans[metrp[i]] = inf; from[metrp[i]] = metrp[i]; } for(int i = 0; i < m; ++i){ cin>>u>>v>>w; e[u].push_back({v,w}); e[v].push_back({u,w}); } solve(); return 0; }