1. 程式人生 > >牛客國慶集訓派對Day3: I. Metropolis(dijkstra)

牛客國慶集訓派對Day3: I. Metropolis(dijkstra)

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
*/