P1122 最大子树和
P1122 最大子树和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目就是要求:树上点权之和最大的一个连通分量
令dp[i]为必须选i节点的情况下,最大的子树点权和
则有转移方程 dp[x]+=max(dp[v],0);
初始化dp[x]=a[x];
注意:最后的答案显然不是dp[1],而是最大的dp[x];
Code:
#include<bits/stdc++.h> using namespace std; #define ll long long #define mp make_pair #define pb push_back #define popb pop_back #define fi first #define se second const int N=2e4+10; //const int M=; //const int inf=0x3f3f3f3f; const ll INF=0x3ffffffffffff; int T,n,a[N],dp[N]; vector<int> g[N]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } void dfs(int x,int fa) { dp[x]=a[x]; for(auto v:g[x]) { if(v==fa) continue; dfs(v,x); if(dp[v]>0) dp[x]+=dp[v]; } } int main() { // freopen("","r",stdin); // freopen("","w",stdout); n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<n;i++) { int u=read(),v=read(); g[u].pb(v); g[v].pb(u); } dfs(1,0); ll ans=-INF; for(int i=1;i<=n;i++) ans=max(ans,1LL*dp[i]); printf("%d",ans); return 0; }