LOJ10160周年纪念晚会

题目描述

Ural 州立大学的校长正在筹备学校的 80 周年纪念聚会。由于学校的职员有不同的职务级别,可以构成一棵以校长为根的人事关系树。每个资源都有一个唯一的整数编号,从 1 到 N 编号,且对应一个参加聚会所获得的欢乐度。为使每个职员都感到快乐,校长设法使每个职员和其直接上司不会同时参加聚会。

你的任务是设计一份参加聚会者的名单,使总欢乐度最高。

输入格式

第一行是一个整数 N

接下来 N 行对应 N 个职员的欢乐度,第 ii 行的一个整数为第 i 个职员的欢乐度 pi

接着是学校的人事关系树,每一行格式为 L K ,表示第 K 个职员是第 L 个职员的直接上司,输入以 0 0 结束。

输出格式

输出参加聚会者获得的最大欢乐度。

样例

样例输入

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

样例输出

5

数据范围与提示

对于100% 的数据,1N6000,128pi127。

——————————————————————————————————————————————————

没有上司的舞会,简单的树形动归。

f[u][0]:表示当前点不参加舞会时,当前子树上的最大欢乐值

f[u][1]:表示当前点参加舞会时,当前子树上的最大欢乐值

f[u][0]=sum( max( f[v][0] , f[v][1] ) )

f[u][1]=sum( f[v][0] ) + w[u]

——————————————————————————————————————————————————

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=6010;
 4 int n;
 5 struct edge
 6 {
 7     int u,v,nxt;
 8 }e[maxn];
 9 int head[maxn],js;
10 void addage(int u,int v)
11 {
12     e[++js].u=u;e[js].v=v;
13     e[js].nxt=head[u];head[u]=js;
14 }
15 int w[maxn],root;
16 bool rd[maxn];
17 int f[maxn][2];
18 void dp(int u,int fa)
19 {
20     f[u][0]=0;f[u][1]=w[u];
21     for(int i=head[u];i;i=e[i].nxt)
22     {
23         int v=e[i].v;
24         if(v!=fa)
25         {
26             dp(v,u);
27             f[u][0]+=max(f[v][0],f[v][1]);
28             f[u][1]+=f[v][0];
29         }
30     }
31 }
32 int main()
33 {
34     scanf("%d",&n);
35     for(int i=1;i<=n;++i)scanf("%d",&w[i]);
36     for(int u,v,i=1;i<n;++i)
37     {
38         scanf("%d%d",&v,&u);
39         addage(u,v);
40         rd[v]=1;
41     }
42     for(int i=1;i<=n;++i)
43         if(rd[i]==0)
44         {
45             root=i;
46             break;
47         }
48     dp(root,0);
49     cout<<max(f[root][0],f[root][1]);
50     return 0;
51 }
View Code
原文地址:https://www.cnblogs.com/gryzy/p/10153723.html