传送门
题意:学校内有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个舞会,舞会每邀请来一个职员都会增加一定的快乐指数Ri,但是,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了.求最大的快乐指数。
分析:一道经典的选择类树形DP问题.既然题目都直白地告诉了说具有树形关系,所以dfs从根节点层层递归下去把树构建出来.根节点当然就是校长了,即没有直接上司的人.设pd[i]表示i有无上司,则有pd[root]=0;
设f[x][0/1]分别表示x不参加/参加舞会的最大快乐指数.既然有两种状态,就有两种转移.
第一种情况:x不参加舞会,则x的下属y可能参加,也可能不参加.
f[x][0]=max(f[x][0],max(f[x][0]+f[y][1],f[x][0]+f[y][0]))
第二种情况:x参加舞会,则x的下属y不可能参加
f[x][1]=max(f[x][1],f[x][1]+f[y][0])
P.S.应该是数据太水,这样讨论就直接一遍过了,看了一下题解,每个人的转移都有一点差别...
int n,root;
int pd[6005],f[6005][2];
vector<int>q[6005];
//q[x]记录q的下属有哪些,相当于直接用vector存图了
void dfs(int x){
for(int i=0;i<q[x].size();i++){
int y=q[x][i];
dfs(y);
f[x][0]=max(f[x][0],max(f[x][0]+f[y][1],f[x][0]+f[y][0]));
f[x][1]=max(f[x][1],f[x][1]+f[y][0]);
}
return;
}
int main(){
n=read();
for(int i=1;i<=n;i++)f[i][1]=read();
for(int i=1;i<=n-1;i++){
int a=read(),b=read();
q[b].push_back(a);//a是b的下属之一
pd[a]=1;
}
int a=read(),b=read();
//根据题意最后还会输出两个0,吞掉.
for(int i=1;i<=n;i++){
if(pd[i]==0){
root=i;
break;
}
}//找到根节点
dfs(root);//从根节点开始dfs
printf("%d
",max(f[root][0],f[root][1]));
return 0;
}