Hdu 1520 Anniversary party【樹形DP】

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1520

題目大意:一個樹上每個結點都有一個權值,在子結點和父結點不能同時選取的情況下,輸出可以選擇的最大值。

設dp[i][0]爲在樹中的i結點裏,不選擇i結點可以獲得的最大值,
dp[i][1]爲在選擇i結點的情況下可以獲得的最大值。

不難看出,當選擇了i結點的時候,i的子結點一定是不可選的,即dp[i][1]=sum(dp[v][0]) (v爲i的子結點)
當不選取i結點的時候,子結點可以選,也可以不選,因爲可能出現負值,所以有可能選取了子結點導致總值更小,所以dp[i][0]=sum(max(dp[v][0],dp[v][1]))(v是i的子結點)

從頂向下遞歸一下就可以求出各結點的值了

代碼

#include <iostream>
#include <vector>

using namespace std;

int rate[6666];//結點值
int father[6666];//結點i的父結點
int dp[6666][2];

vector<int> tree[6666];

void dfs(int v)
{
    int len=tree[v].size();
    dp[v][0]=0;
    dp[v][1]=rate[v];
    if(len==0)
        return ;
    for(int i=0 ; i<len ; i++)
    {
        dfs(tree[v][i]);
        dp[v][0]+=max(dp[tree[v][i]][0],dp[tree[v][i]][1]);
        dp[v][1]+=dp[tree[v][i]][0];
    }
}


int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=1 ; i<=n ; i++)
        {
            cin>>rate[i];
        }
        for(int i=1 ; i<=n ; i++)
        {
            father[i]=i;
            tree[i].clear();
        }
        while(1)
        {
            int a,b;
            cin>>a>>b;
            if(a==0&&b==0)
                break;
            father[a]=b;
            tree[b].push_back(a);
        }
        int root;
        for(int i=1 ; i<=n ; i++)//找祖先
        {
            if(father[i]==i)
            {
                root=i;
                break;
            }
        }
        dfs(root);
        cout<<max(dp[root][0],dp[root][1])<<endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章