题目链接:传送门
Description
某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大。
Solution
这是一道树形DP入门的水题
我们设dp[i][0]表示不选i时的最大活跃值,dp[i][1]表示选i时的最大活跃值,那么有:
(j为i的儿子) dp[i][0]+=max(dp[j][0],dp[j][1]) dp[i][1]+=dp[j][0]
这样只要dfs一遍就能将答案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; }
|