题目描述
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% 的数据,1≤N≤6000,−128≤pi≤127。
——————————————————————————————————————————————————
没有上司的舞会,简单的树形动归。
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 }