解题思路
f
i
f_i
fi表示以i为根节点的最大子树和,$ f_i
的
初
值
就
是
a
i
。
如
果
i
的
子
节
点
权
值
>
0
,
i
的初值就是a_i 。 如果i 的子节点权值>0,i
的初值就是ai。如果i的子节点权值>0,i就可以保留这个子节点,那么:
f
i
=
a
i
+
m
a
x
{
f
s
o
n
,
0
}
f_i=a_i+max\{f_{son},0\}
fi=ai+max{fson,0}
最后
f
i
f_i
fi 取
m
a
x
max
max,注意有负数,所以赋初值要赋小。
代码
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
int n,k,head[32010],x,y;
long long ans,f[16010],r[16010];
struct c{
int x,next;
}a[32010];
void add(int x,int y){
a[++k].x=y;
a[k].next=head[x];
head[x]=k;
}
void dfs(int dep,int fa){
f[dep]=r[dep];
for(int i=head[dep];i;i=a[i].next)
{
int y=a[i].x;
if(y==fa)continue;
dfs(y,dep);
if(f[y]>0)
f[dep]+=f[y];
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&r[i]);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
memset(f,128,sizeof(f));
dfs(1,0);
ans=-0x7fffffff;
for(int i=1;i<=n;i++)
ans=max(ans,f[i]);
printf("%lld",ans);
}
/*
10
44 20 -91 90 -82 74 40 -38 -4 -26
2 1
3 1
4 2
5 4
6 5
7 3
8 2
9 4
10 3
8*/