【邻接表】【树状DP】没有上司的晚会

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 N1行,每行输入一对整数 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);
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值