链接:https://www.nowcoder.com/acm/contest/203/I
来源:牛客网
题目描述
魔方国有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
解题思路:考虑暴力,求出两点间的最短路径,明显不可取。但是题目只是要求某些点之间的最短路径,考虑优化。我们从某一个要求的点出发,用迪杰斯特拉求最短路径,第一个碰到的要求的点,就是该点的答案,我们记录即可。我们对所有的点都做一遍这个操作,即可求得答案,但是这样的复杂度感觉降低了(因为提前退出了迪杰斯特拉),实际上没有降低。那么我们考虑优化,我们用堆优化的迪杰斯特拉去求最短路,很容易就会想到,我们把所有要求的点在一开始就入队,然后做一遍迪杰斯特拉即可,当碰到要求的点时我们更新最短路径即可。这里有两种情况,一种是真的走到了要求的点,一种是走到了一半,这里直接用染色的思想处理即可。
#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
typedef long long ll;
const int MAXN=2000005;
const ll INF=0x3f3f3f3f3f3f3f3f;
struct edge{
int u;
int v;
int w;
int next;
}e[MAXN];
int edge_num=0;
int head[MAXN];
void insert_edge(int u,int v,int w){
e[edge_num].u=u;
e[edge_num].v=v;
e[edge_num].w=w;
e[edge_num].next=head[u];
head[u]=edge_num++;
}
struct node{
int v;
ll dis;
node (ll a,int b):dis(a),v(b){};
bool operator <(const node &rhs)const
{
return dis > rhs.dis;
}
};
int N,M,K;
bool vis[MAXN];
int P[MAXN];
ll d[MAXN];
ll ans[MAXN];
int belong[MAXN];
void dijkstra(){
priority_queue<node> que;
memset(d,0x3f,sizeof(d));
memset(vis,0,sizeof(vis));
memset(ans,0x3f,sizeof(ans));
for(int i=0;i<K;i++)
que.push(node(d[P[i]]=0,P[i]));
while(!que.empty()){
node tp=que.top();
que.pop();
int u=tp.v;
if(vis[u])
continue;
vis[u]=1;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].v;
int w=e[i].w;
if(d[v]>d[u]+w)//如果碰到了,此条件必然不成立,因为初始为0
{
d[v]=d[u]+w;
que.push(node(d[v],v));
belong[v]=belong[u];//将从该点出发求最短路径的过程都染色
}else if(belong[u]!=belong[v])//如果不同颜色就更新答案
{
ans[belong[u]]=min(ans[belong[u]],d[u]+d[v]+w);
ans[belong[v]]=min(ans[belong[v]],d[u]+d[v]+w);
}
}
}
}
int main(){
scanf("%d%d%d",&N,&M,&K);
edge_num=0;
memset(head,-1,sizeof(head));
for(int i=0;i<K;i++){
scanf("%d",&P[i]);
belong[P[i]]=P[i];
}
int u,v,w;
for(int i=0;i<M;i++){
scanf("%d%d%d",&u,&v,&w);
insert_edge(u,v,w);
insert_edge(v,u,w);
}
dijkstra();
for(int i=0;i<K;i++)
printf("%lld ",ans[P[i]]);
return 0;
}