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]
f[0][i]是第
i
i
i个不来
f
[
1
]
[
i
]
f[1][i]
f[1][i]是第
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;
}