hdu 1520 Anniversary party

树形dp。
dp[i][1]表示第i个雇员参加party能获得的最大活跃积分,dp[i][0]表示第i个雇员不参加Party能获得的最大活跃积分。
即得状态转移方程:
dp[i][0]+=max(dp[k][0],dp[k][1])
dp[i][1]+=max(dp[k][0]); //k表示第i个雇员的直接下属
(若第i个雇员去参加party,则要加上本身的活跃积分。
很久没有做树形dp,看了别人的解题报告才想出树形dp的做法。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=6005;
vector<int> a[maxn];
int n;
int soc[maxn];
int dp[maxn][2];
int f[maxn]; //树根标记
void DP(int t) //任意一个节点
{
    dp[t][1]+=soc[t];
    if(!a[t].size())
        return;
    for(int i=0;i<a[t].size();i++)
    {
        DP(a[t][i]);
        dp[t][0]+=max(dp[a[t][i]][0],dp[a[t][i]][1]);
        dp[t][1]+=dp[a[t][i]][0];
    }
    return;
}
int main()
{
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&soc[i]);
            a[i].clear();
            f[i]=-1;
            dp[i][0]=dp[i][1]=0;
        }
        int t1,t2;
        while(scanf("%d%d",&t1,&t2)&&t1+t2)
        {
            a[t2].push_back(t1);
            f[t1]=t2;
        }
        t1=1;
        while(f[t1]!=-1) t1=f[t1];
        DP(t1);
        cout<<max(dp[t1][0],dp[t1][1])<<endl;
    }
    return 0;
}

你可能感兴趣的:(树形DP)