【CodeVS 1380】没有上司的舞会

【题目】

传送门

题目描述 Description

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

输入描述 Input Description

第一行一个整数 n n ( 1 n 6000 ) (1\le n\le6000)

接下来 n n 行,第 i + 1 i+1 行表示 i i 号职员的快乐指数 r i r_i ( 128 r i 127 ) (-128\le r_i\le127)

接下来 n 1 n-1 行,每行输入一对整数 l , k l,k 。表示 k k l l 的直接上司。

最后一行输入 0 , 0 0,0

输出描述 Output Description

输出最大的快乐指数。

样例输入 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


【分析】

一道比较简单的树形 D P \mathrm{DP} 题。

f i , 0 / 1 f_{i,0/1} 表示以 i i 为根的子树中, i i 不参加 / / 参加舞会的最大快乐指数。

那么显然可知(设 j j i i 的儿子):

f i , 1 = f j , 0 f_{i,1}=\sum f_{j,0}

f i , 0 = m a x ( f j , 0 , f j , 1 ) f_{i,0}=\sum max(f_{j,0},f_{j,1})

最后的答案 a n s = m a x ( f r o o t , 0 , f r o o t , 1 ) ans=max(f_{root,0},f_{root,1})

其中 r o o t root 是整棵树的根(不一定是 1 1 )。


【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 6005
using namespace std;
int n,t,root;
int val[N],fa[N],f[N][2];
int first[N],v[N],nxt[N];
void add(int x,int y)
{
	nxt[++t]=first[x];
	first[x]=t,v[t]=y;
}
void dp(int x)
{
	int i,k;
	f[x][1]=val[x];
	for(i=first[x];i;i=nxt[i])
	{
		k=v[i],dp(k);
		f[x][1]+=f[k][0];
		f[x][0]+=max(f[k][1],f[k][0]);
	}
}
int main()
{
	int x,y,i;
	scanf("%d",&n);
	for(i=1;i<=n;++i)
	  scanf("%d",&val[i]);
	for(i=1;i<n;++i)
	{
		scanf("%d%d",&x,&y);
		add(y,x),fa[x]=y;
	}
	for(i=1;i<=n;++i)
	  if(!fa[i])  root=i;
	dp(root);
	printf("%d",max(f[root][0],f[root][1]));
	return 0;
}

猜你喜欢

转载自blog.csdn.net/forever_dreams/article/details/88928677
今日推荐