其他分享
首页 > 其他分享> > [Acwing蓝桥杯DP] 1220. 生命之树

[Acwing蓝桥杯DP] 1220. 生命之树

作者:互联网

题目链接:1220. 生命之树 - AcWing题库

题目大意:给n个节点的一颗树,树上的每个节点都有一个权值为w,求这颗树的子数的最大权值和。

数据范围:1<= n <=1e5

                  w<=1e6 , w有可能是负数 由于数据比较大,可能爆int 要用long long

分析:

这个题要用树形DP,实际上终点还是dfs和状态方程的定义

这里,集合表示:f [ i ] , 表示以i为头结点的子树的最大权值和

f [ i ] 用dfs求,时间复杂度是O(n)

初始化 f [ i ] = w [ i ] ; //头结点包括自己的值

结果res= max( f [ i ] , res ) ;

注意:w有可能为负数 如果f [ i ]为负数,则不取。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N=1e5+10,M=N*2;

int n;
int w[N];
int h[N],e[M],ne[M],idx;
LL f[N];

void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void dfs(int u,int father)
{
    f[u]=w[u];
    
    for(int i=h[u];~i;i=ne[i])
    {
        int j=e[i];
        if(j!=father)
        {
            dfs(j,u);
            f[u]+=max(0LL,f[j]);
        }
    }
}

int main()
{
    memset(h,-1,sizeof(h));
    cin>>n;
    for(int i=1;i<=n;i++)cin>>w[i];
    
    for(int i=0;i<n-1;i++)
    {
        int a,b;
        cin>>a>>b;
        add(a,b);
        add(b,a);
    }
   
    dfs(1,-1);//第二个参数是父节点,防止重复来回搜。
    
    LL res=f[1];
    for(int i=2;i<=n;i++)
    {
        res=max(res,f[i]);
    }
    
    printf("%lld",res);
    
    return 0;
}

END!!!

标签:idx,1220,int,res,LL,ne,dfs,蓝桥,之树
来源: https://www.cnblogs.com/qinmo/p/16084737.html