题目链接:传送门

Description

某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大。

Solution

这是一道树形DP入门的水题 我们设dp[i][0]dp[i][0]表示不选i时的最大活跃值,dp[i][1]表示选i时的最大活跃值,那么有: (j为i的儿子) dp[i][0]+=max(dp[j][0],dp[j][1])dp[i][0]+=\max(dp[j][0],dp[j][1]) dp[i][1]+=dp[j][0]dp[i][1]+=dp[j][0] 这样只要dfs一遍就能将答案max(dp[root][0],dp[root][1])\max(dp[root][0],dp[root][1])求出了

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define begin Begin
#define next Next
using namespace std;
const int maxn=6000+10;
int p[maxn];
int dp[maxn][2];
int n;
int fa[maxn];
inline void dfs(int x){
for(int i=1;i<=n;i++)
if(fa[i]==x && !p[i]){
p[i]=1;
dfs(i);
dp[x][0]+=max(dp[i][0],dp[i][1]);
dp[x][1]+=dp[i][0];
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("POJ2342.in","r",stdin);
freopen("POJ2342.out","w",stdout);
#endif
while(scanf("%d",&n)!=EOF){
memset(fa,0,sizeof(fa));
memset(p,0,sizeof(p));
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)scanf("%d",&dp[i][1]);
int root=0;
int x,y;
while(scanf("%d%d",&x,&y),x||y){
root=y;
fa[x]=y;
}
while(fa[root])root=fa[root];//求树的根
p[root]=1;
dfs(root);
printf("%d\n",max(dp[root][0],dp[root][1]));
}
return 0;
}