URAL 1039 Anniversary Party

    由于上司的关系构成了一颗树,于是我们可以从树形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;    

}

 

你可能感兴趣的:(part)