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的答案。
输入
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
*/