题目链接:https://ac.nowcoder.com/acm/contest/5944/I
题目大意:
n节点的一棵树。燃完一条边长度为L的边需要2*L的时间。现在m个点同时点火。问树什么时候彻底燃完。
思路:多源最短路,建立超级源点。连接这m个点。跑最短路。枚举每条边。染完的最短时间。取得
max。 一条u-v-w边:dis[u]+a=b+dis[v]并且a+b=w。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const LL maxn=500005;
const LL mod=1e9+7;
LL n, m, dis[maxn], vis[maxn], cut=0;
struct node{
LL to, w, next;
}e[maxn];
LL head[maxn];
void addcut(LL u,LL v, LL w){
e[cut].to=v,e[cut].w=w, e[cut].next=head[u],head[u]=cut++;
}
priority_queue<pair<LL, LL> > q;
void dijkstra(LL s, LL t){
q.push({0, s}); dis[s]=0;
while(!q.empty()){
pair<LL, LL> pos=q.top(); q.pop();
if(vis[pos.second]){
continue;
}
vis[pos.second]=1;
for(LL i=head[pos.second];i>=0;i=e[i].next){
if(!vis[e[i].to]&&dis[e[i].to]>dis[pos.second]+e[i].w){
dis[e[i].to]=dis[pos.second]+e[i].w;
q.push({-dis[e[i].to], e[i].to});
}
}
}
}
int main(){
LL n, m, x, y, z;
scanf("%lld%lld", &n, &m);
memset(head, -1, sizeof(head)); cut=0;
memset(dis, 0x7f, sizeof(dis));
memset(vis, 0, sizeof(vis));
for(LL i=1; i<n; i++){
scanf("%lld%lld%lld", &x, &y, &z);
addcut(x, y, z*2); addcut(y, x, z*2);
}
for(int i=1; i<=m; i++){
int x; scanf("%d", &x);
addcut(0, x, 0);
}
dijkstra(0, n);
LL mx=0;
for(int i=1; i<=n; i++){
for(LL k=head[i];k>=0;k=e[k].next){
LL x=e[k].to;
LL pos1=dis[x], pos2=dis[i], d=e[k].w;
mx=max(mx, pos2+(d+pos1-pos2)/2);
}
}
printf("%lld\n", mx);
return 0;
}
京公网安备 11010502036488号