- 传统题 1000ms 512MiB
-
说明
Ural 州立大学的校长正在筹备学校的 80 周年纪念聚会。由于学校的职员有不同的职务级别,可以构成一棵以校长为根的人事关系树。每个资源都有一个唯一的整数编号,从 1到 N 编号,且对应一个参加聚会所获得的欢乐度。为使每个职员都感到快乐,校长设法使每个职员和其直接上司不会同时参加聚会。 你的任务是设计一份参加聚会者的名单,使总欢乐度最高。
输入格式
第一行是一个整数 N; 接下来 N 行对应 N 个职员的欢乐度,第 i 行的一个整数为第 i 个职员的欢乐度
; 接着是学校的人事关系树,每一行格式为
L K
,表示第 K 个职员是第 L 个职员的直接上司,输入以0 0
结束。输出格式
输出参加聚会者获得的最大欢乐度。
样例
输入数据 1
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
输出数据 1
5
提示
数据范围:对于 100%的数据,1≤N≤6000,−128≤≤127。
-
#include<bits/stdc++.h> using namespace std; int f[500005][2],v[500005],in[500005],n,k,l,head[500005],to[500005],ne[500005],tot; void add(int u, int v) { ++tot; to[tot] = v; ne[tot] = head[u]; head[u] = tot; } void dfs(int u){ f[u][0]=0; f[u][1]=v[u]; int vv; for(int i=head[u];i;i=ne[i]) { vv=to[i]; dfs(vv); f[u][0]+=max(f[vv][0],f[vv][1]); f[u][1]+=f[vv][0]; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&v[i]); while(cin>>l>>k&&(k!=0||l!=0)) { add(k,l); in[l]++; } int root=0; for(int i=1;i<=n;i++) if(in[i]==0) root=i; dfs(root); cout<<max(f[root][0],f[root][1]); return 0; }
#A. 「一本通 5.2 练习 3」周年纪念晚会(树的最优独立集)
![](https://img-home.csdnimg.cn/images/20240711042549.png)