题意:
有个公司要举行一场晚会。为了让到会的每个人不受他的直接上司约束而能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会再邀请他的直接的上司,但该人的上司的上司,上司的上司的上司等都可以邀请。已知每个人最多有唯一的一个上司。
已知公司的每个人参加晚会都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大。
思路:
树形DP入门题
①先设定:数组dp[i][0]为第i个人参加了舞会的时候这个子树的欢乐值之和
数组dp[i][1]为第i个人没参加舞会的时候这个子树的欢乐值之和
②由此我们可以推出对于i的状态转移方程为
dp[i][0] = a[i]+ ∑dp[j][1] (i为j的父亲节点)
dp[i][1] = ∑Max(dp[j][1],dp[j][0]) (i为j的父亲节点)
#include#include #include #include using namespace std; const int maxn=6003; int a[maxn],dp[maxn][2]; int n; vector<int> edge[maxn]; void dfs(int x,int fa) { dp[x][0]=a[x],dp[x][1]=0; for(int i=0;i ){ if(edge[x][i]!=fa){ dfs(edge[x][i],x); dp[x][0]+=dp[edge[x][i]][1]; dp[x][1]+=max(dp[edge[x][i]][0],dp[edge[x][i]][1]); } } } int main() { while(scanf("%d",&n)!=EOF){ for(int i=1;i<=n;i++) scanf("%d",&a[i]); int l,k; for(int i=1;i<=n;i++) edge[i].clear(); memset(dp,0,sizeof(dp)); while(scanf("%d%d",&l,&k)&&l&&k){ edge[l].push_back(k); edge[k].push_back(l); } dfs(1,0); printf("%d\n",max(dp[1][0],dp[1][1])); } return 0; }