POJ Anniversary party 树形DP

/*
树形dp:
给一颗树,要求一组节点,节点之间没有父子关系,并且使得所有的节点的权值和最大
对于每一个节点,我们有两种状态
dp[i][0]表示不选择节点i,以节点i为根的子树所能形成的节点集所能获得的最大权值和 
dp[i][1]表示选择节点i ,同上!

转移方程:
dp[i][0]+=max(dp[i_son][1],dp[i_son][0])如果没选择的话,那么子树可选择可不选择 
dp[i][1]+=dp[i_son][0] 选择了之后,子树只能不选择
最后输出max(dp[i][0],dp[i][1])即可
*/ 
 
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define maxn 6002
vector<int> v[maxn];
bool b[maxn];
int dp[maxn][2],hp[maxn];
void dfs(int k)
{
    int i,len=v[k].size();
    dp[k][0]=0 ;
    dp[k][1]=hp[k];
    if(len==0)
    return ;
    for(i=0;i<len;i++)
    {
        dfs(v[k][i]);
        dp[k][0]+=max(dp[v[k][i]][1],dp[v[k][i]][0]);
        dp[k][1]+=dp[v[k][i]][0];
    }
}
int main()
{
    int i,n;
    int k,l;
    while(cin>>n)
    {
        for(i=1;i<=n;i++)
        cin>>hp[i],v[i].clear();
        memset(b,0,sizeof(b));
        while(cin>>l>>k&&k||l)
        {
            v[k].push_back(l);
            b[l]=1;
        }
        for(i=1;i<=n;i++)
        {
            if(!b[i])
                break;
        }
        b[i]=1;
        dfs(i);
        cout<<max(dp[i][1],dp[i][0])<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/qscqesze/p/4104263.html