题目链接: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=1<<30; const int maxn=6007; const double pi=acos(-1); const int mod=1e9+7; int fa[maxn],vis[maxn]; int root; int dp[maxn][2];int n; void dp_rule(int root){ vis[root]=1; for(int i=1;i<=n;i++){ if(fa[i]==root&&!vis[i]){ //vis[i]=1; dp_rule(i);//注意这里一定要先遍历,之后再加在dp数组上 dp[root][0]+=max(dp[i][0],dp[i][1]);//上司不去,下属去或不去选大的一个 dp[root][1]+=dp[i][0];//上司去,下属只能不去 } } } int main(){ while(~scanf("%d",&n)){ memset(vis,0,sizeof(vis)); memset(fa,0,sizeof(fa)); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++)scanf("%d",&dp[i][1]);//输入这里要注意啊 int l,k; while(~scanf("%d%d",&l,&k)){ if(l==0&&k==0)break; fa[l]=k; } for(int i=1;i<=n;i++){ if(!fa[i]){ root=i; break; } } dp_rule(root); int ans=max(dp[root][0],dp[root][1]); cout<<ans<<endl; } return 0; }