Description
Ural大学有 N N N个职员,编号为 1 1 1~ N N N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。
Input
第一行一个整数
N
N
N。
(
1
<
=
N
<
=
6000
)
(1<=N<=6000)
(1<=N<=6000)
接下来
N
N
N行,第
i
+
1
i+1
i+1行表示i号职员的快乐指数
R
i
Ri
Ri。
(
−
128
<
=
R
i
<
=
127
)
(-128<=Ri<=127)
(−128<=Ri<=127)
接下来
N
−
1
N-1
N−1行,每行输入一对整数
L
L
L,
K
K
K。表示
K
K
K是
L
L
L的直接上司。
最后一行输入0,0。
Output
输出最大的快乐指数。
Sample Input
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
Sample Output
5
解题思路
用邻接表存,
a
a
a为邻接表,
.
y
.y
.y指向员工,
b
b
b储存职员链的起始位置。
(不知道链表的,出门左拐百度)
设
f
[
r
o
o
t
]
[
1
]
f[root][1]
f[root][1]为第
r
o
o
t
root
root个职员参加晚会的最优值
f
[
r
o
o
t
]
[
0
]
f[root][0]
f[root][0]为第
r
o
o
t
root
root个职员不参加晚会的最优值
- 第 r o o t root root个职员参加,Ta的所有直接员工都不能参加,则 f [ r o o t ] [ 1 ] = f [ r o o t ] [ 1 ] + f [ a [ i ] . y ] [ 0 ] ; f[root][1]=f[root][1]+f[a[i].y][0]; f[root][1]=f[root][1]+f[a[i].y][0];
- 第
r
o
o
t
root
root个职员不参加,Ta的员工可参加可不参加,取开心值最大值,则
f [ r o o t ] [ 0 ] = f [ r o o t ] [ 0 ] + m a x ( f [ a [ i ] . y ] [ 0 ] , f [ a [ i ] . y ] [ 1 ] ) ; f[root][0]=f[root][0]+max(f[a[i].y][0],f[a[i].y][1]); f[root][0]=f[root][0]+max(f[a[i].y][0],f[a[i].y][1]);
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=6010;
struct DT{
int y;
int next;
}a[maxn];
int b[maxn],n,s[maxn],f[maxn][2],num,Gun;
bool t[maxn];
void dp(int root){
f[root][1]=s[root];//初始开心值为自己
for(int i=b[root];i;i=a[i].next){
dp(a[i].y);
f[root][1]=f[root][1]+f[a[i].y][0];//参加
f[root][0]=f[root][0]+max(f[a[i].y][0],f[a[i].y][1]);//不参加
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&s[i]);
for(int i=1;i<n;i++){
int k,l;
scanf("%d%d",&l,&k);//k是上司,l是员工
t[l]=1;
a[++num].y=l;
a[num].next=b[k];
b[k]=num;//存入链表
}
for(int i=1;i<=n;i++){
if(!t[i]){//没有上司的顶头上司(%%%)
dp(i);
Gun=max(Gun,max(f[i][0],f[i][1]));//最后的答案也要取开心值最大值
}
}
printf("%d",Gun);
}