树形dp练习题一
(被考研复试机试折磨)我爱算法!!!!
dp[u][0]表示u这个人去舞会的情况下的最大快乐值,dp[u][1]表示在u这个人不去参加舞会的情况下的最大快乐值。
对于任意节点u来说,设其孩子节点为p,
1、dp[u][0]的值为其孩子节点的dp[p][1](其孩子不能去)的总和。
2、dp[u][1]的值为其孩子节点dp[p][1]与dp[p][0]的最大值总和(孩子节点可以去也可以不去,选择能使快乐最大的那种情况)。
(ps:类似于在每个节点进行决策,根据去或者不去两种情况导致的不同快乐值来决定改节点是否去舞会。)
代码如下:
// An highlighted block
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
vector <int> edge[6010];
int weight[6010];//用于存储快乐指数
int dp[6010][2]={0};//0表示去,1表示不去
int n;
int flag[6010];//用于标识根节点
void dfs(int u)
{
if(edge[u].size()==0) //边界条件,叶子节点去或不去不会影响其他人参加
{
dp[u][0]=weight[u];
dp[u][1]=0;
return;
}
for(int i=0;i<edge[u].size();i++)
{
dfs(edge[u][i]);
dp[u][0]+=dp[edge[u][i]][1];//上司去,下属必不能去
dp[u][1]+=max(dp[edge[u][i]][0],dp[edge[u][i]][1]);//上司不去,下属选择去或不去,取其中的最大值。
}
dp[u][0]+=weight[u];
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>weight[i];
}
for(int i=0;i<n-1;i++)
{
int a,b;
cin>>a>>b;
edge[b].push_back(a);
flag[a]=1;
}
int root;
for(int i=1;i<=n;i++)
{
if(flag[i]==0)
{
root=i;
break;
}
}
//cout<<root;
dfs(root);
cout<<max(dp[root][0],dp[root][1]);
return 0;
}
提交测试
过啦!!!!