题目大意:给定一棵树,每个点带点权,请你求出点权和最大的联通块和是多少。
树形DP简单题
设f[x]为以x为根的子树,含x的联通块点权最大和。对于每个v(v∈son(x)),只要f[v]不是负数就把v选上。
f[x]=∑max(f[son(x)],0)
#include<iostream> #include<iomanip> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; inline int read() { char ch; bool bj=0; while(!isdigit(ch=getchar())) bj|=(ch==‘-‘); int res=ch^(3<<4); while(isdigit(ch=getchar())) res=(res<<1)+(res<<3)+(ch^(3<<4)); return bj?-res:res; } void printnum(int x) { if(x>9)printnum(x/10); putchar(x%10+‘0‘); } inline void print(int x,char ch) { if(x<0) { putchar(‘-‘); x=-x; } printnum(x); putchar(ch); } int f[16005],a[16005],h[16005]; struct Edge { int to,nxt; } w[16005<<1]; int cnt,n; inline void AddEdge(int x,int y) { w[++cnt].to=y; w[cnt].nxt=h[x]; h[x]=cnt; } int ans=-0x3f3f3f3f; void DFS(int x,int fa) { for(int i=h[x]; i; i=w[i].nxt) { int v=w[i].to; if(v==fa)continue; DFS(v,x); f[x]+=max(f[v],0); } f[x]+=a[x]; ans=max(ans,f[x]); } signed main() { n=read(); for(int i=1; i<=n; i++)a[i]=read(); int x,y; for(int i=1; i<n; i++) { x=read(); y=read(); AddEdge(x,y); AddEdge(y,x); } DFS(1,0); print(ans,‘\n‘); return 0; }
原文:https://www.cnblogs.com/soledadstar/p/11379698.html