由于上司的关系构成了一颗树,于是我们可以从树形dp的角度去考虑问题。不妨用f[cur][0]表示不选当前节点时这棵子树value的最大值,f[cur][1]表示选当前节点时这棵子树value的最大值,那么如果不选当前节点,它的子节点就可选也可不选,因此f[cur][0]要加上所有子节点x的Max{f[x][1],f[x][0]},而如果选当前节点,它的子节点必然不能选,因此f[cur][1]要加上所有子节点x的f[x][0]以及当前节点本身的value。

#include<stdio.h>
#include<string.h>
#define MAXD 6010
int N, first[MAXD], next[MAXD], v[MAXD], e, dgr[MAXD];
int a[MAXD], f[MAXD][2];
int Max(int x, int y)
{
    return x > y ? x : y;    
}
void add(int x, int y)
{
    v[e] = y;
    next[e] = first[x], first[x] = e ++;    
}
void init()
{
    int i, L, K;    
    memset(dgr, 0, sizeof(dgr));
    memset(first, -1, sizeof(first));
    e = 0;
    for(i = 1; i <= N; i ++)
        scanf("%d", &a[i]);
    for(;;)
    {
        scanf("%d%d", &L, &K);
        if(!L && !K)
            break;
        add(K, L), ++ dgr[L];
    }
}
void dp(int cur)
{
    int i, max, sum;
    max = sum = 0;
    for(i = first[cur]; i != -1; i = next[i])
    {
        dp(v[i]);
        max += Max(f[v[i]][0], f[v[i]][1]);
        sum += f[v[i]][0];    
    }
    f[cur][1] = sum + a[cur];
    f[cur][0] = max;
}
void solve()
{
    int i, j, k, ans = 0;
    for(i = 1; i <= N; i ++)
        if(dgr[i] == 0)
        {
            dp(i);
            ans += Max(f[i][0], f[i][1]);    
        }    
    printf("%d\n", ans);
}
int main()
{
    while(scanf("%d", &N) == 1)
    {
        init();
        solve();    
    }
    return 0;    
}

 

posted on 2012-05-04 14:02  Staginner  阅读(221)  评论(0编辑  收藏  举报