题意:公司开晚会,每个人都有对应的活跃度,他们都不希望自己的上司来,邀请哪些人能使活跃度最大
分析:dp(i,0)表示第i个人不来 dp(i,1)表示第i个人来
dp(root,1) += dp(i,0) 上司来了,那么下属就不回来
dp(root,0) += max(dp(i,0),dp(i,1)) 上司不来,下属可来可不来
这样只要从根节点开始进行一遍dfs即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 6005;
int c[maxn],father[maxn],visit[maxn];
int n;
int dp[maxn][2]; //dp(i,0)表示i不来满意度值,dp(i,1)表示i来满意度值
void tree_dp(int node){
visit[node] = 1;
for(int i = 1;i <= n;i++){
if(!visit[i] && father[i] == node){
tree_dp(i);
dp[node][0] += max(dp[i][1],dp[i][0]);
dp[node][1] += dp[i][0];
}
}
}
int main(){
int a,b;
while(scanf("%d",&n) != EOF){
memset(father,0,sizeof(father));
memset(visit,0,sizeof(visit));
memset(dp,0,sizeof(dp));
for(int i = 1;i <= n;i++){
scanf("%d",&dp[i][1]);
}
int flag = 1;
int root = 0;
while(scanf("%d%d",&a,&b) && (a||b)){
father[a] = b;
if(root = a || flag){
root = b;
}
}
while(father[root]){
root = father[root];
}
tree_dp(root);
printf("%d\n",max(dp[root][0],dp[root][1]));
}
return 0;
}