Description
某大学有 nn 个职员,编号为 1\ldots n1…n。
他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。
现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 r_iri,但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。
所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。
Input
输入的第一行是一个整数 nn。
第 22 到第 (n + 1)(n+1) 行,每行一个整数,第 (i+1)(i+1) 行的整数表示 ii 号职员的快乐指数 r_iri。
第 (n + 2)(n+2) 到第 2n2n 行,每行输入一对整数 l, kl,k,代表 kk 是 ll 的直接上司。
Output
输出一行一个整数代表最大的快乐指数。
Sample 1
| Inputcopy | Outputcopy |
|---|---|
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 | 5 |
Hint
数据规模与约定
对于 100\%100% 的数据,保证 1\leq n \leq 6 \times 10^31≤n≤6×103,-128 \leq r_i\leq 127−128≤ri≤127,1 \leq l, k \leq n1≤l,k≤n,且给出的关系一定是一棵树。
题解:
设
f[x][0]表示以x为根的子树,且x不参加舞会的最大快乐值
f[x][1]表示以x为根的子树,且x参加了舞会的最大快乐值
则f[x][0]=sigma{max(f[y][0],f[y][1])} (y是x的儿子)
f[x][1]=sigma{f[y][0]}+h[x] (y是x的儿子)
先找到唯一的树根root
则ans=max(f[root][0],f[root][1])
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- using namespace std;
- const int maxn = 6010;
- vector<int> g[maxn];
- int n,h[maxn],f[maxn][2],p[maxn],rt;
-
-
- void dfs(int u){
- int sz = g[u].size();
- f[u][1] = h[u];
- for(int i = 0; i < sz; i++){
- //遍历u的每一个子节点
- int v = g[u][i];
- dfs(v);
- f[u][1] += f[v][0];
- f[u][0] += max(f[v][0], f[v][1]);
- }
-
- }
-
- int main(){
- scanf("%d",&n);
- for(int i = 1; i <= n; i++)
- scanf("%d",&h[i]);
- for(int i = 1; i < n; i++){
- int a,b;
- scanf("%d%d",&a,&b);
- p[a] = b;//a的父节点是b
- g[b].push_back(a);//b的子节点
- }
- for(int i = 1; i <= n; i++){
- if(!p[i]){
- rt = i;//找到根节点
- break;
- }
- }
- dfs(rt);
- printf("%d\n", max(f[rt][0], f[rt][1]));
-
- return 0;
- }