【codevs1380】没有上司的舞会 树形dp

题目描述

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

输入

第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。
最后一行输入0,0。

输出

输出最大的快乐指数。

样例输入

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

样例输出

5


题解

裸的树形dp。

f[x]代表x参加时最大快乐指数,g[x]代表x不参加时最大快乐指数。

那么易推得f[x]=r[x]+∑g[son[x][i]],g[x]=∑max(f[son[x][i]],g[son[x][i]])。

答案即为max(f[root],g[root])。

#include <stdio.h>
#include <vector>
using namespace std;
int f[6001] , g[6001] , r[6001];
bool mark[6001];
vector<int> son[6001];
void dp(int x)
{
    f[x] = r[x];
    int i , y;
    for(i = 0 ; i < (int)son[x].size() ; i ++ )
    {
        y = son[x][i];
        dp(y);
        f[x] += g[y];
        g[x] += max(f[y] , g[y]);
    }
}
int main()
{
    int n , i , x , y , root = 0;
    scanf("%d" , &n);
    for(i = 1 ; i <= n ; i ++ )
        scanf("%d" , &r[i]);
    for(i = 1 ; i <= n - 1 ; i ++ )
    {
        scanf("%d%d" , &x , &y);
        mark[x] = 1;
        son[y].push_back(x);
    }
    scanf("%d%d" , &x , &y);
    for(i = 1 ; i <= n ; i ++ )
        if(!mark[i])
            root = i;
    dp(root);
    printf("%d\n" , max(f[root] , g[root]));
    return 0;
}
posted @ 2016-12-13 19:52  GXZlegend  阅读(462)  评论(0编辑  收藏  举报