【DP】没有上司的舞会

Description

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

Input

第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数L,K。表示K是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
前言

邻接链表是个非常恶心而神奇的东西,很难理解,
我是小学六年级一节数学课上搞懂的
其实并不需要完全理解,只要知道它非常的神奇,和拥有能够运用它的智慧。

思路

首先,我们用邻接链表存储这一系列关系,然后从上司下手,把所有去和不去的可能算出来,然后判断去和不去哪个大。
f [ 0 ] [ i ] f[0][i] 是第 i i 个不来
f [ 1 ] [ i ] f[1][i] 是第 i i 个来

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
struct nm
{
	int n,l,t;
}wh[10005];
int a[10005],f[2][10005],h[10005],p[10005];
int n,tt,l,r,ans;
void g(int l,int r)
{
	wh[++tt].t=r;//上司
	wh[tt].l=l;//下属
	wh[tt].n=h[r];
	h[r]=tt;
}
void dp(int now)
{
	f[1][now]=a[now];
	for(int i=h[now];i;i=wh[i].n)//把所有下属for一遍
	{
		dp(wh[i].l);//把下属dp一遍
		f[1][now]=f[1][now]+f[0][wh[i].l];
		//如果上司来了,那么他的下属就不可以来
		f[0][now]=max(f[1][wh[i].l],f[0][wh[i].l])+f[0][now];
		//如果上司不来了,那么他的下属来与不来都可以,所以判断来大,还是不来大
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d",&a[i]);
	for(int i=1;i<=n-1;++i)
	{
		scanf("%d%d",&l,&r);
		g(l,r);//存入邻接链表
		p[l]=1;//赋值为不是上司
	}
	scanf("%d%d",&l,&r);
	for(int i=1;i<=n;++i)
		if(!p[i])dp(i),ans=i;//dp只有下属的人,然后ans为第几个
	printf("%d",max(f[1][ans],f[0][ans]));//看上司来和不来谁大
	return 0;
}

猜你喜欢

转载自blog.csdn.net/SSL_wujiajie/article/details/84992357
今日推荐