您的位置:首页 > 其它

POJ 2342 Anniversary party【树形DP】

2016-04-28 23:24 411 查看
树形dp入门题,给n个人参加聚会,每个人有个活跃度,他们之间有上司和下属关系,如果上司参加了则下属不去参加,求最大活跃度(上司和下属关系都是直接关系,不需要考虑间接的情况)。

定义

dp[rt][0]:以rt为根的树,rt本身不来的最大活跃度
dp[rt][1]:以rt为根的树,rt本身来的最大活跃度




dp[rt][1] = dp[rt][1] + dp[sonI][0];      //上司来,则下属不能来
dp[rt][0] = dp[rt][0] + max(dp[sonI][0],dp[sonI][1]);  //上司不来,下属可来可不来


代码就好写了,不过需要先找到根节点,再往下递归求方程,最后输出max( dp[root][0], dp[root][1] )即可。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define clr( a , x ) memset ( a , x , sizeof (a) );
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define SpeedUp std::cout.sync_with_stdio(false);

const int maxn = 6005;
const int inf = 0x3f3f3f3f;
int father[maxn];
int dp[maxn][2];
int vis[maxn];
int n;

void tree(int rt){
vis[rt] = 1;
for (int i = 1; i <= n; ++i){
if(!vis[i] && father[i] == rt){    //下属
tree(i);
dp[rt][1] += dp[i][0];              //上司来,则下属不能来
dp[rt][0] += max(dp[i][0],dp[i][1]);    //上司不来,下属可来可不来
}
}
}

int main(){
int p,q;

while(cin>>n){
clr(vis,0);
clr(dp,0);
clr(father,0);
for (int i = 1; i <= n; ++i){
cin>>dp[i][1];
}
while(cin>>p>>q,p||q){
father[p] = q;
}

int rt = 1;         //1号人肯定在
while(father[rt]){  //从任意一点开始找根节点
rt = father[rt];
}
tree(rt);
cout<<max(dp[rt][0],dp[rt][1])<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: