有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少?
5 1 2 3 4 5 1 2 1 3 2 4 2 5
12
#include <cstdio> using namespace std; int val[100001],dp[100001],son[100001],gson[100001],first[100001],next[200002],to[200002],que[100001],far[100001]; bool vis[100001]; int main() { int n,i,u,v,ans; while(~scanf("%d",&n)) { for(i=1;i<=n;i++) first[i]=-1,vis[i]=son[i]=gson[i]=dp[i]=0; for(i=1;i<=n;i++) scanf("%d",&val[i]); for(i=0;i<n-1;i++) { scanf("%d%d",&u,&v); to[i*2]=v; next[i*2]=first[u]; first[u]=i*2; to[i*2+1]=u; next[i*2+1]=first[v]; first[v]=i*2+1; } int top=0,bottom=1; que[top]=1; vis[que[top]]=1; far[1]=-1; while(top<bottom)//建树 { for(int e=first[que[top]];e!=-1;e=next[e]) { if(!vis[to[e]]) { vis[to[e]]=1; que[bottom++]=to[e]; far[to[e]]=que[top];//记录父亲节点 } } top++; } ans=0; for(i=bottom-1;i>=0;i--)//从树的最下面一层开始往上推 { dp[que[i]]=val[que[i]]+gson[que[i]]>son[que[i]]?val[que[i]]+gson[que[i]]:son[que[i]]; ans=ans>dp[que[i]]?ans:dp[que[i]]; if(far[que[i]]!=-1) { son[far[que[i]]]+=dp[que[i]];//更新父节点的son值 if(far[far[que[i]]]!=-1) gson[far[far[que[i]]]]+=dp[que[i]];//更新祖父节点的gson值 } } printf("%d\n",ans); } }
wust-1299-结点选择(树形DP),布布扣,bubuko.com
原文:http://blog.csdn.net/faithdmc/article/details/25244693