描述
Ural 州立大学的校长正在筹备学校的 80 周年纪念聚会。由于学校的职员有不同的职务级别,可以构成一棵以校长为根的人事关系树。每个资源都有一个唯一的整数编号,从 1 到 N 编号,且对应一个参加聚会所获得的欢乐度。为使每个职员都感到快乐,校长设法使每个职员和其直接上司不会同时参加聚会。
你的任务是设计一份参加聚会者的名单,使总欢乐度最高。
输入
第一行是一个整数 N ;
接下来 N 行对应 N 个职员的欢乐度,第 ii行的一个整数为第i 个职员的欢乐度pi
接着是学校的人事关系树,每一行格式为 L K ,表示第 K 个职员是第 L 个职员的直接上司,输入以 0 结束。
输出
输出参加聚会者获得的最大欢乐度。
样例输入
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
简单树形dp,都不用怎么说了吧
表示以为根的子树,当前这个点选还是不选的的最大值
很容易得到递推方程
;
直接递归求解
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
int f[6005][2],n,m,fa[6005],a[6005],adj[12005],nxt[12005],to[12005],cnt;
inline void addedge(int u,int v){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
}
inline void dfs(int u,int fa){
f[u][0]=0,f[u][1]=a[u];
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(v==fa)continue;
dfs(v,u);
f[u][0]+=max(f[v][0],f[v][1]);
f[u][1]+=f[v][0];
}
}
int main(){
n=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<n;i++){
int u=read(),v=read();
addedge(v,u);fa[u]=v;
}
read(),read();
int p;
for(int i=1;i<=n;i++)if(!fa[i]){p=i;break;}
dfs(p,0);
cout<<max(f[p][0],f[p][1])<<'
';
}