题目链接: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;
}