2013寒假练习 1018:没有上司的聚会

来源:互联网 发布:sai是什么绘图软件 编辑:程序博客网 时间:2024/05/17 00:49

地址:http://acm.bit.edu.cn/mod/programming/view.php?a=504

树形DP好题。终于独立做出一道题。。

题意:给出一棵树的节点的权值,取一个节点集满足没有节点有父子关系,求这个节点集总权值的最大值。

由于当前节点是否取影响其父亲的DP取值,故DP时要分取和不取两种情况。状态转移方程还是比较好想的,可以参见代码。

然后就是具体处理,我是用父亲表示法存树(parent),初始先将所有叶子节点入队,然后依次更新它们的父亲的DP值;用辅助数组child找出他们的父亲并入队。。一直到树根,输出树根的两个DP值中最大的那个。

#include<iostream>#include<queue>using namespace std;#define SIZE 100005int child[SIZE];   //未被处理的孩子个数 int parent[SIZE];  //记录父亲int dp[2][SIZE];   //dp[0][]表示不选该节点时子树的最大价值。dp[1][]表示选int a[SIZE];int main(){int n,i,now,t1,t2;while(~scanf("%d",&n)){memset(child,0,sizeof(child));memset(dp,0,sizeof(dp));for(i=1;i<=n;i++)  scanf("%d",&a[i]);for(i=1;i<=n-1;i++){scanf("%d%d",&t1,&t2);parent[t1]=t2,child[t2]++;}queue<int>q;for(i=1;i<=n;i++){if(!child[i])         //找到初始处于最底层的(没有孩子),初始化边界条件并入队{dp[0][i]=0,dp[1][i]=a[i];q.push(i);}                        }for(i=1;i<n;i++)       //对当前已得到DP值的该层节点,以之更新上一层的值{now=q.front();dp[0][parent[now]]+=dp[0][now]>dp[1][now]?dp[0][now]:dp[1][now];          //状态转移方程。不取根就可以取或不取孩子,取了根只能不取孩子dp[1][parent[now]]+=dp[0][now];child[parent[now]]--;                                                    if(child[parent[now]]==0)             //若上一层某节点孩子全部处理完毕,则入队{q.push(parent[now]);  dp[1][parent[now]]+=a[parent[now]];       //dp[1][]因为取了树根最后还要加上树根的值}q.pop();}printf("%d\n",dp[0][q.front()]>dp[1][q.front()]?dp[0][q.front()]:dp[1][q.front()]);}return 0;}


 

 

原创粉丝点击