[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!!!

posted @   秦末  阅读(85)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
1 博文导航目录
点击右上角即可分享
微信分享提示