您的位置:首页 > 其它

POJ 2342 (树状DP)入门

2016-08-11 12:05 453 查看
入门比较好的博客

#include "cstdio"
#include "iostream"
#include "cstring"
#include "algorithm"
using namespace std;
const int MAX=6005;
/*
树形dp 入门
题意:公司举办 晚会,为了提高活跃度(每个人都有自己的活跃度),
下属不能和直接上司一起出现,问最大活跃度
题解: dp[i][0] 第i个人不来 初始化为 0
dp[i][1] 第i个人来 初始化为活跃度
从叶子节点往上积累,
// 上司来,下属不来
dp[root][1] += dp[i][0];
// 上司不来,下属来,也可能不来 ,选最大
dp[root][0] += max(dp[i][0],dp[i][1]);

*/
int n;
int dp[MAX][2],father[MAX];
// dp[i][0] 表示不去
// dp[i][1] 表示去
int vis[MAX];
int tree_dp(int root)
{
int i;
vis[root]=1;
for(int i=1;i<=n;i++)
{// 遍历所有点
if(!vis[i] && father[i]== root)
{// i是root的下属
tree_dp(i); // 找到了root下属 ,找到叶子,从叶子节点往上dp
dp[root][1] += dp[i][0];// 上司来,下属不来
dp[root][0] += max(dp[i][0],dp[i][1]);// 上司不来,下属来,也可能不来 ,选最大
}
}
}
int main()
{
while(~scanf("%d",&n))
{
memset(dp,0,sizeof(dp));
memset(father,0,sizeof(father));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
scanf("%d",&dp[i][1]);//每个去的人的价值
}
int root=0;// 记录父节点
int u,v;
while(scanf("%d%d",&u,&v) &&u+v)
{
father[u]=v;
//若根节点是u,那么将根节点转到v
if(root == u)
root=v;
}
//查找父节点,
while(father[root])
root=father[root];
tree_dp(root);
int ans=max(dp[root][1],dp[root][0]);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: