题目连接:https://www.luogu.org/problem/show?pid=1122
解题思路:
这是一道类似于树形DP的题。
我们可以用求最大字段和的方法求最大子树和,所以问题就转化成了如何在遍历树记录子树和。
我们可以用f[x]数组储存以x为根的子树和,一直搜到它最远的儿子,然后返回时如果当前的值>0就说明能产生影响,就加上,然后标记该点,用ans储存最大的子树和就行了。
#include<iostream>
#include<cstdio>
using namespace std;
#define N 17000
struct node{
int from,to;
}list[N*2];
int head[N],a[N],f[N],x,y,n,s,v[N],ans;
void add(int x,int y){
list[++s].from=head[x];
list[s].to=y;
head[x]=s;
}
int dfs(int x){
int sum=0;
if (f[x]) return f[x];
for (int i=head[x];i;i=list[i].from){
if (!v[list[i].to]){
v[list[i].to]=1;
int t=dfs(list[i].to);
if (t>0)sum+=t;
}
}
f[x]=sum+a[x];
ans=max(ans,f[x]);
return f[x];
}
int main(){
cin>>n;
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=1;i<n;i++){
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
v[1]=1;
dfs(1);
cout<<ans;
return 0;
}