树状DP HDU1520 Anniversary party

时间:2021-09-03 07:06:35

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520

题意:职员之间有上下级关系,每个职员有自己的happy值,越高在派对上就越能炒热气氛。但是必须是他的上司不在场的情况。求派对happy值的和最大能是多少。

PS:这是多组输入,一开始还没看出来。。。

dp[i][0]代表第i个职员不来的情况下的快乐值,dp[i][1]是第i个职员来的情况下的快乐值

那很显然有

dp[上司][来] += dp[下属][不来];
dp[上司][不来] += Max(dp[下属][来],dp[下属][不来]);

树状DP其实和普通DP没啥大差,就是需要遍历来确定子节点,这个题做起来还是不难的

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=<<;
const int maxn=;
const double pi=acos(-);
const int mod=1e9+;
int fa[maxn];
int root;
int dp[maxn][];int n;
void dp_rule(int root){for(int i=;i<=n;i++){
if(fa[i]==root){
//vis[i]=1;
dp_rule(i);//注意这里一定要先遍历,之后再加在dp数组上
dp[root][]+=max(dp[i][],dp[i][]);//上司不去,下属去或不去选大的一个
dp[root][]+=dp[i][];//上司去,下属只能不去
}
}
}
int main(){
while(~scanf("%d",&n)){
memset(vis,,sizeof(vis));
memset(fa,,sizeof(fa));
memset(dp,,sizeof(dp));
for(int i=;i<=n;i++)scanf("%d",&dp[i][]);//输入这里要注意啊
int l,k;
while(~scanf("%d%d",&l,&k)){
if(l==&&k==)break;
fa[l]=k;
}
for(int i=;i<=n;i++){
if(!fa[i]){
root=i;
break;
}
}
dp_rule(root);
int ans=max(dp[root][],dp[root][]);
cout<<ans<<endl; }
return ;
}