P1352 没有上司的舞会(树形DP)

 

某大学有N个职员,编号为1~N。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。


分析:树形结构同DP一样,本身具有子结构的性质。

所以考虑dp[u][1]和dp[u][0]分别为节点u选和不选时,以它为根的子树的答案。

如果它不选,子节点可选可不选,取最大的那个;如果它选,子节点只能不选;

所以

dp[u][0]=Σmax(dp[son][0],dp[son][1])

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

搜到某个点时初始化

dp[u][0]=0

dp[u][1]=v[u]

就能自下而上推出根节点的dp值,输出较大的一个即可。

时间复杂度只有O(n)。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int v[6003],dp[6003][2],fa[6003],n,a,b;
 4 vector<int> tree[6003];
 5 
 6 void dfs(int u){
 7     dp[u][0]=0;
 8     dp[u][1]=v[u];
 9     for(int i=0;i<tree[u].size();i++){
10         int son=tree[u][i];
11         dfs(son);
12         dp[u][0]+=max(dp[son][1],dp[son][0]);
13         dp[u][1]+=dp[son][0];
14     }
15 }
16 
17 int main(){
18     memset(fa,-1,sizeof(fa)); 
19     cin>>n;
20     for(int i=1;i<=n;i++)
21       cin>>v[i];
22   for(int i=1;i<=n;i++){
23       cin>>a>>b;
24         if(!a&&!b)break;
25         tree[b].push_back(a);
26         fa[a]=b; 
27     }
28     int t=1;
29     while(fa[t]!=-1)t=fa[t];
30     dfs(t);
31     cout<<max(dp[t][1],dp[t][0]); 
32 }
View Code

 

posted @ 2020-02-18 00:12  _vv123  阅读(141)  评论(0编辑  收藏  举报