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; }