HDU1520 Anniversary party(树形DP入门)

俺的第一道树形DP问题,在树形DP上倒下了太多次!只要是带树的题,大概率是树形DP。。。

题意:

有个公司要举行一场晚会。为了让到会的每个人不受他的直接上司约束而能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会再邀请他的直接的上司,但该人的上司的上司,上司的上司的上司……都可以邀请。已知每个人最多有唯一的一个上司。

已知公司的每个人参加晚会都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大。

题解:

做法是树形DP

dp[i][0]表示不邀请i的最大值

dp[i][1]表示邀请i的最大值

状态转移方程:

dp[u][1]+=dp[v][0]

dp[u][0]+=max(dp[v][1],dp[v][0])

所有的dp[v][1]初始化为对应的气氛值

#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
int N;
int dp[maxn][2];
//dp[i][0]表示不邀请i的最大值
//dp[i][1]表示邀请i的最大值 
int son[maxn];
vector<int> g[maxn];
int visit[maxn];
void dfs (int u) {
    visit[u]=1;
    for (int i=0;i<g[u].size();i++) {
        int v=g[u][i];
        if (visit[v]) continue;
        dfs(v);
        dp[u][1]+=dp[v][0];
        dp[u][0]+=max(dp[v][1],dp[v][0]); 
    } 
}
int main () {
    scanf("%d",&N);
    for (int i=1;i<=N;i++) {
        scanf("%d",&dp[i][1]);
    }
    int u,v;
    while (scanf("%d%d",&u,&v)&&u) {
        g[v].push_back(u);
        son[u]++;
    }
    int root;
    for (root=1;root<=N;root++)
        if (!son[root]) break;
    dfs(root);
    printf("%d\n",max(dp[root][1],dp[root][0]));
    return 0; 
}

 

posted @ 2020-04-05 21:48  zlc0405  阅读(131)  评论(0编辑  收藏  举报