题解 :树形dp
f[i]表示从i出发只能向下走最终回到i的最大值,f1[i]表示从i出发只能向下走停在某颗子树的最大值,
f2[i]表示从i出发只能向下走停在某颗子树的次大值
g[i]表从i出发只能向上最终回到i的最大值,g1[i]表示从i出发只能向上最终不回到i的最大值。
然后正反两遍dfs就可以了,写的时候有很多细节需要处理,用f更新g的时候要注意有些点的权值和边权没有加入f,所以计算的时候也不用减去。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 300003
using namespace std;
int n,m,f[N],g[N],f1[N],f2[N],mark[N],g1[N];
int point[N],next[N*2],v[N*2],c[N*2],val[N],tot;
void add(int x,int y,int z)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=z;
}
void dfs(int x,int fa)
{
f2[x]=f1[x]=f[x]=val[x];
int maxn=0; int maxx=0; int maxn1=0; int maxx1=0;
int size=0;
for (int i=point[x];i;i=next[i]){
if (v[i]==fa) continue;
dfs(v[i],x); size++;
g[v[i]]=f[v[i]]-2*c[i];
if (g[v[i]]>0)
{
f[x]+=g[v[i]]; mark[v[i]]=0;
int t=f1[v[i]]-f[v[i]]+c[i];
if (t>=maxn)
maxx1=maxx,maxn1=maxn,maxx=v[i],maxn=t;
else if (t>maxn1) maxn1=t,maxx1=v[i];
}
else if (f1[v[i]]-c[i]>=maxn)
maxx1=maxx,maxn1=maxn,maxn=f1[v[i]]-c[i],maxx=v[i];
else if (f1[v[i]]-c[i]>maxn1) maxn1=f1[v[i]]-c[i],maxx1=v[i];
}
f1[x]=f[x]+maxn; mark[maxx]=1;
f2[x]=f[x]+maxn1; mark[maxx1]=2;
}
void dfs1(int x,int fa)//f 能加的都加了,f1加入了不返回的最大值,f2中加入了不返回的次大值。
{
for (int i=point[x];i;i=next[i]){
if (v[i]==fa) continue;
int t=0;
if (mark[v[i]]==1) {
int t=0;
if (f[v[i]]-2*c[i]>0) t=-f[v[i]]+c[i];
g[v[i]]=max(0,g[x]+f[x]+t+(t==0?-2*c[i]:-c[i]));
g1[v[i]]=max(g[x]+f2[x]+t+(t==0?-c[i]:0),g1[x]+f[x]+t+(t==0?-c[i]:0));
}
else
if (mark[v[i]]!=-1) {
int t=0;
if (f[v[i]]-2*c[i]>0) t=-f[v[i]]+c[i];
g[v[i]]=max(0,g[x]+f[x]+t+(t==0?-2*c[i]:-c[i]));
g1[v[i]]=max(g[x]+f1[x]+t+(t==0?-c[i]:0),g1[x]+f[x]+t+(t==0?-c[i]:0));
}
else {
g[v[i]]=max(0,g[x]+f[x]-2*c[i]);
g1[v[i]]=max(0,max(g[x]+f1[x]-c[i],g1[x]+f[x]-c[i]));
}
dfs1(v[i],x);
}
}
int main()
{
freopen("treasure.in","r",stdin);
freopen("treasure.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<n;i++){
int x,y,z; scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
memset(mark,-1,sizeof(mark));
for (int i=1;i<=n;i++) scanf("%d",&val[i]);
dfs(1,0);
memset(g,0,sizeof(g));
dfs1(1,0);
//for (int i=1;i<=n;i++)
// cout<<f[i]<<" "<<f1[i]<<" "<<f2[i]<<" "<<g[i]<<" "<<g1[i]<<endl;
for (int i=1;i<=n;i++)
{
int t=max(f[i]+g1[i],f1[i]+g[i]);
if (i==1) printf("%d\n",f1[i]);
else printf("%d\n",t);
}
}