[Acwing蓝桥杯DP] 1220. 生命之树
题目大意:给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!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人