#include <bits/stdc++.h>
using namespace std;
const int maxn=5e5+1;
typedef long long ll;
struct node{
int y,len,next;
}a[maxn<<1];
int n,k,head[maxn<<1],cnt=0,vis[maxn]={0},t;
ll size[maxn];//以1为根时,子树含有的国家数量
ll max1[maxn];//以1为根时,子树到国家的最长路径
ll max2[maxn];//以1为根时,子树到国家的次长路径
ll sum[maxn];//以1为根时,子树到国家的路径总和
ll num[maxn];//路径最长的那个子树节点
ll father[maxn];//通过父亲节点能到达的国家的最长路径
ll ans[maxn];//答案
void add(int x,int y,int z)
{
a[cnt].y=y;a[cnt].len=z;a[cnt].next=head[x];head[x]=cnt++;
}
void dfs1(int u,int fa)
{
if(vis[u]) size[u]=1;
for(int i=head[u];i!=-1;i=a[i].next)
{
int v=a[i].y,w=a[i].len;
if(v==fa) continue;
dfs1(v,u);
size[u]+=size[v];
sum[u]+=sum[v];
if(size[v])
{
sum[u]+=2*w;
if(max1[v]+w>max1[u])
{
max2[u]=max1[u];
max1[u]=max1[v]+w;
num[u]=v;
}
else max2[u]=max(max2[u],max1[v]+w);
}
}
}
void dfs2(int u,int fa)
{
for(int i=head[u];i!=-1;i=a[i].next)
{
int v=a[i].y,w=a[i].len;
if(v==fa) continue;
if(k-size[v]) father[v]=max(father[u],(num[u]==v)?max2[u]:max1[u])+w;//树的中心求法
ans[v]=ans[u];
if(size[v]) ans[v]-=2*w;
if(k-size[v]) ans[v]+=2*w;
dfs2(v,u);
}
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d %d",&n,&k);
for(int i=1;i<n;++i)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);add(v,u,w);
}
for(int i=1;i<=k;++i)
{
scanf("%d",&t);
vis[t]=1;
}
dfs1(1,0);
ans[1]=sum[1];
dfs2(1,0);
for(int i=1;i<=n;++i) printf("%lld\n",ans[i]-max(father[i],max1[i]));
}
2020 CCPC-Wannafly Winter Camp Day3 G 火山哥周游世界(树形dp)
猜你喜欢
转载自blog.csdn.net/qq_42479630/article/details/104138016
今日推荐
周排行