Ural P1039 没有上司的晚会___树形dp

版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/Gx_Man_VIP/article/details/79627788

题目大意;

Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数Ri。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。

1<=N<=6000
-128<=Ri<=127

题解:

一道树形dp的模板题,
因为只存在一棵树,所以只需要找到根节点然后树形dp即可
f[i][0]表示以i为根的子树没有选上司i的最大快乐指数
f[i][1]表示以i为根的子树选了上次i的最大快乐指数
因为选了i的儿子就不能选i
那么就有了很显然的转移:
f[i][0]=max{f[i][0],max{f[i][0]+f[son][0],f[i][0]+f[son][1]} }
f[i][1]=max{f[i][1],f[i][1]+f[son][0]}

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 6005

int f[N][2],a[N],next[N],list[N],op[N],x[N],n,m,y;

int max(int aa,int bb)
{
     if (aa>bb) return aa;
     return bb;
}

void add(int rp,int aa)
{
     next[rp]=list[aa];
     list[aa]=rp;   
}

void dfs(int dep)
{
     f[dep][0]=0;
     f[dep][1]=a[dep];   
     int rp=list[dep];
     while (rp)
           {
                int i=x[rp];
                dfs(i);
                f[dep][0]=max( f[dep][0] , max(f[dep][0]+f[i][0] , f[dep][0]+f[i][1]) );
                f[dep][1]=max( f[dep][1] , f[dep][1]+f[i][0] );
                rp=next[rp];
           }
}

int main()
{
    scanf("%d",&n);
    for (int i=1; i<=n; i++) scanf("%d",&a[i]);
    for (int i=1; i<n; i++)
         {
             scanf("%d%d",&x[i],&y);
             if (x[i]==0&&y==0) break;
             add(i,y);
             op[x[i]]=1;
         }
    int root;
    for (int i=1; i<=n; i++)
         if (!op[i]) root=i;
    dfs(root);
    printf("%d",max(f[root][0],f[root][1]));
    return 0; 
}

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页