牛客國慶集訓派對Day3: I. Metropolis(dijkstra)
阿新 • • 發佈:2018-12-13
I. Metropolis
題目描述
魔方國有n座城市,編號為。城市之間通過n-1條無向道路連線,形成一個樹形結構。 在若干年之後,其中p座城市發展成了大都會,道路的數量也增加到了m條。 大都會之間經常有貿易往來,因此,對於每座大都會,請你求出它到離它最近的其它大都會的距離。
輸入描述:
第一行三個整數n,m,p (1 ≤ n,m ≤ 2*105,2 ≤ p ≤ n),第二行p個整數表示大都會的編號 (1≤ xi≤ n)。接下來m行每行三個整數ai,bi,li表示一條連線ai和bi,長度為li的道路 (1 ≤ ai,bi ≤ n,1 ≤ li ≤ 109)。 保證圖是連通的。
輸出描述:
輸出一行p個整數,第i個整數表示xi的答案。
示例1
輸入
5 6 3 2 4 5 1 2 4 1 3 1 1 4 1 1 5 4 2 3 1 3 4 3
輸出
3 3 5
只需要求每個大都會離它最近的大都會的最短路
那麼將所有大都會同時設為起點,之後按照dijkstra的規則加邊,如果加完某條邊後區其中兩個大都會聯通了,那麼更新下答案即可
這樣因為每條邊最多隻會被加一次,所以複雜度是O(mlogn)的
#include<stdio.h> #include<string.h> #include<algorithm> #include<map> #include<string> #include<math.h> #include<queue> #include<stack> #include<iostream> using namespace std; #define LL long long #define mod 1000000007 typedef struct Road { LL len; int x, y, id; bool operator < (const Road &b) const { if(len>b.len) return 1; return 0; } }Road; vector<Road> G[200005]; LL dp[200005], ans[200005]; int poi[200005], a[200005], vis[200005]; priority_queue<Road> q; int main(void) { Road now, temp; int x, y, n, m, p, i, j, v; scanf("%d%d%d", &n, &m, &p); memset(dp, -1, sizeof(dp)); for(i=1;i<=p;i++) scanf("%d", &a[i]); for(i=1;i<=m;i++) { scanf("%d%d%lld", &x, &y, &now.len); now.id = i; now.x = x, now.y = y, G[x].push_back(now); now.x = y, now.y = x, G[y].push_back(now); } for(i=1;i<=p;i++) { x = a[i]; poi[x] = i, dp[x] = 0; for(j=0;j<G[x].size();j++) { q.push(G[x][j]); vis[G[x][j].id] = 1; } } while(q.empty()==0) { now = q.top(); q.pop(); if(dp[now.y]==-1) { dp[now.y] = now.len; poi[now.y] = poi[now.x]; for(i=0;i<G[now.y].size();i++) { v = G[now.y][i].y; temp.x = now.y, temp.y = v; if(vis[G[now.y][i].id]==0) { temp.len = G[now.y][i].len+dp[now.y]; q.push(temp); vis[G[now.y][i].id] = 1; } } } else if(poi[now.x]!=poi[now.y]) { //printf("%d %d %d %d\n", now.x, now.y, poi[now.x], poi[now.y]); if(ans[poi[now.x]]==0) ans[poi[now.x]] = now.len+dp[now.y]; else ans[poi[now.x]] = min(ans[poi[now.x]], now.len+dp[now.y]); if(ans[poi[now.y]]==0) ans[poi[now.y]] = now.len+dp[now.y]; else ans[poi[now.y]] = min(ans[poi[now.y]], now.len+dp[now.y]); } } v = 0; for(i=1;i<=n;i++) { if(ans[i]!=0) { if(v==1) printf(" "); printf("%lld", ans[i]); v = 1; } } puts(""); return 0; } /* 5 6 2 2 5 1 2 4 1 3 1 1 4 1 1 5 4 2 3 1 3 4 3 */