[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!!!
标签:idx,1220,int,res,LL,ne,dfs,蓝桥,之树 来源: https://www.cnblogs.com/qinmo/p/16084737.html