【codevs1380】没有上司的舞会 树形dp
题目描述
Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。
输入
第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数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
题解
裸的树形dp。
f[x]代表x参加时最大快乐指数,g[x]代表x不参加时最大快乐指数。
那么易推得f[x]=r[x]+∑g[son[x][i]],g[x]=∑max(f[son[x][i]],g[son[x][i]])。
答案即为max(f[root],g[root])。
#include <stdio.h> #include <vector> using namespace std; int f[6001] , g[6001] , r[6001]; bool mark[6001]; vector<int> son[6001]; void dp(int x) { f[x] = r[x]; int i , y; for(i = 0 ; i < (int)son[x].size() ; i ++ ) { y = son[x][i]; dp(y); f[x] += g[y]; g[x] += max(f[y] , g[y]); } } int main() { int n , i , x , y , root = 0; scanf("%d" , &n); for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &r[i]); for(i = 1 ; i <= n - 1 ; i ++ ) { scanf("%d%d" , &x , &y); mark[x] = 1; son[y].push_back(x); } scanf("%d%d" , &x , &y); for(i = 1 ; i <= n ; i ++ ) if(!mark[i]) root = i; dp(root); printf("%d\n" , max(f[root] , g[root])); return 0; }