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

Description

Ural大学有 N N 个职员,编号为 1 1 ~ N N 。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。

Input

第一行一个整数 N N ( 1 < = N < = 6000 ) (1<=N<=6000)
接下来 N N 行,第 i + 1 i+1 行表示i号职员的快乐指数 R i Ri ( 128 < = R i < = 127 ) (-128<=Ri<=127)
接下来 N 1 N-1 行,每行输入一对整数 L L , K K 。表示 K K 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 为邻接表, . y .y 指向员工, b b 储存职员链的起始位置。
(不知道链表的,出门左拐百度)
f [ r o o t ] [ 1 ] f[root][1] 为第 r o o t root 个职员参加晚会的最优值
  f [ r o o t ] [ 0 ] f[root][0] 为第 r o o t root 个职员不参加晚会的最优值

  • r o o t 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];
  • r o o t 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]);

#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);
} 
发布了45 篇原创文章 · 获赞 0 · 访问量 366

猜你喜欢

转载自blog.csdn.net/qq_39940018/article/details/103535895