pku 2342 Hoj 1520

http://acm.pku.edu.cn/JudgeOnline/problem?id=2342

http://acm.hdu.edu.cn/showproblem.php?pid=1520

同一道树形Dp题,我的第一道树形DP;

最简单的树形DP了;

题意:有一个大学的庆典晚会,想邀请一些在大学任职的人来参加,每个人有自己的搞笑值,但是现在遇到一个问题就是如果两个人之间有直接的上下级关系,那么他们的搞笑值将会降低,为了使每个到晚会的人都很尽兴,所以决定只邀请部分人来参加,绝对不邀请有直接上下级关系的两个人,求搞笑值的我最大值。

分析:这个题很明显给出的是一棵树,不难想到这道题是树形DP,是一个树,它们之间必有一定的层次关系,而对于每一个而言它只有两种结果,要么被邀请要么没被邀请,那么他的邀请与否与他的下级有关,如果他被邀请那么他的下级绝对不能被邀请;如果他没有被邀请那么将不影响他下级被邀请与否;那么我们从最底层开始向上枚举每个人是否被邀请,并且记录其搞笑值总和;

得:Tree[idx].Invite+=Tree[child].Not_Invite;

      Tree[idx].Not_Invite+=Tree[child].Max();

其中Tree[idx].Invite表示已idx为根节点时,该根节点被邀请时得到的最大搞笑值;

其中Tree[idx].Not_Invite表示已idx为根节点时,该根节点没有被邀请时得到的最大搞笑值;

今天还在sha崽大牛那里学到树的父子兄弟结构。。。^^.......

代码:

#include<stdio.h>
#include<algorithm>
using namespace std;
const int N = 6005;
struct node
{
       int father;
       int brother;
       int child;
       int Invite;
       int Not_Invite;
       int Max()
       {
             if(Invite>Not_Invite) return Invite;    
             return Not_Invite;
       }      
       void Init()
       {
             father=brother=child=Not_Invite=0;
       }
}Tree[N];
int n;
void Dfs(int idx)
{
         int child;
         child=Tree[idx].child;
         while(child)
         {
                   Dfs(child);
                   Tree[idx].Invite+=Tree[child].Not_Invite;       
                   Tree[idx].Not_Invite+=Tree[child].Max();       
                   child=Tree[child].brother;
         }
}
int main()
{  
        while(scanf("%d",&n)!=EOF)
        {
             for(int i=1;i<=n;i++)
             {
                        scanf("%d",&Tree[i].Invite);
                        Tree[i].Init();                        
             }
             int a,b;
             while(scanf("%d%d",&a,&b)&&(a+b))
             {
                        Tree[a].father=b;
                        Tree[a].brother=Tree[b].child;                       
                        Tree[b].child=a;
             }
             int i,ans;
             for(i=1;i<=n;i++)
                        if(!Tree[i].father)
                        {
                              Dfs(i);
                              break;
                        }         
             ans=max(Tree[i].Invite,Tree[i].Not_Invite);
             printf("%d/n",ans); 
       }
       return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值