【输入格式】
第一行一个整数N。(1<=N<=6000)接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。最后一行输入0,0。输出最大的快乐指数。
树形DP经典题目,f[i][0]表示不取第i个点的最大值,f[i][1]表示取第i个点的最大值。
ans=max(f[root][0],f[root][1])
#include<iostream> #include<queue> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int n; int f[6005][2],r[6005],cnt,h[6005],fa[6005],root,s[6005]; struct que { int to,next; }w[6005]; void add(int x,int y) { cnt++; w[cnt].to=y; w[cnt].next=h[x]; h[x]=cnt; } void dfs(int u) { if(!s[u]) { f[u][1]=r[u];//根节点的f[u][1]为它的点权 return ; } for(int i=h[u];i;i=w[i].next) { int to=w[i].to; dfs(to); f[u][1]+=f[to][0];//f[u][1]为所有儿子节点不取时的和加上权值 if(f[to][0]>=f[to][1]) f[u][0]+=f[to][0];//f[u][0]取儿子节点中取与不取的较大值,因为可能存在它与儿子都不来的最大情况 else { f[u][0]+=f[to][1]; } } f[u][1]+=r[u]; return ; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&r[i]); } for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); add(y,x); fa[x]=y; s[y]++; } for(int i=1;i<=n;i++) { if(!fa[i]) { root=i; break; } } dfs(root); printf("%d",max(f[root][0],f[root][1])); }
