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)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }