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