P1122 最大子树和(树形dp)

P1122 最大子树和

大水题

随便找一个点做根,蓝后累计子树和。

子树和<0的话不取就行了

顺便找个最大值输出

end.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#define re register
using namespace std;
void read(int &x){
    char c=getchar();x=0; bool f=1;
    while(!isdigit(c)) f=(f&&c!='-'),c=getchar();
    while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
    x=f?x:-x;
}
int max(int &a,int &b){return a>b?a:b;}
#define N 16002
int n,f[N],val[N],ans=-2147483647;
int cnt,hd[N],nxt[N<<1],ed[N],poi[N<<1];
void adde(int x,int y){
    nxt[ed[x]]=++cnt; hd[x]=hd[x]?hd[x]:cnt;
    ed[x]=cnt; poi[cnt]=y;
}
void dfs(int x,int fa){
    f[x]=val[x];
    for(int i=hd[x];i;i=nxt[i]){
        int to=poi[i];
        if(to==fa) continue;
        dfs(to,x);
        if(f[to]>0) f[x]+=f[to];//子树和>0才取
    }ans=max(ans,f[x]);
}
int main(){
    read(n); int q1,q2;
    for(re int i=1;i<=n;++i) read(val[i]);
    for(re int i=1;i<n;++i){
        read(q1); read(q2);
        adde(q1,q2); adde(q2,q1);
    }dfs(1,0);
    printf("%d",ans);
    return 0;
}