牛客练习赛78 C CCA的子树

https://ac.nowcoder.com/acm/contest/11168/C

 

类似于dp求树的直径

在以x为根的子树内,求x的子树里的最大和次大的x的子树的子树和,要求最大和次大不能在x的同一个子节点里。

每次以子节点的最大子树和更新x的最大子树和

最后再用x的子树和更新x的最大子树和

 

#include<cstdio>
#include<algorithm>

using namespace std;

#define N 200001

typedef long long LL;

int a[N];
int front[N],to[N<<1],nxt[N<<1],tot; 

LL sum[N],mx[N];
LL ans=-1e18;

void add(int u,int v)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
}

void dfs(int x,int y)
{
    sum[x]=a[x];
    int t;
    LL maxn=-1e18;
    for(int i=front[x];i;i=nxt[i])
    {
        t=to[i];
        if(t==y) continue;
        dfs(t,x);
        sum[x]+=sum[t];
        ans=max(ans,mx[t]+maxn);
        maxn=max(maxn,mx[t]);
    }
    mx[x]=max(maxn,sum[x]);    
}

int main()
{
    int n,u,v;
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    for(int i=1;i<n;++i)
    {
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    sum[0]=-1e18;
    dfs(1,0);
    if(ans==-1e18) printf("Error");
    else printf("%lld",ans); 
}

 

posted @ 2021-03-15 13:38  TRTTG  阅读(62)  评论(0编辑  收藏  举报