[Ural1039]没有上司的晚会

Description

有个公司要举行一场晚会。
为了能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会邀请他的上司
(上司的上司,上司的上司的上司……都可以邀请)。
每个参加晚会的人都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大。

Input

第1行一个整数N(1<=N<=6000)表示公司的人数。
接下来N行每行一个整数。第i行的数表示第i个人的气氛值x(-128<=x<=127)。
接下来每行两个整数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

题目大意:
给你一棵有n个节点的树,每个节点上都有一个值,现要求在每一对子节点和父节点不同时选的情况下这棵树最大值。

题解
其实我们可以从一个子节点来推出父节点,一个节点无非两种状态,选或不选,那么我们就可以从这两种状态着手。
选:初始值为这个节点的值,并且我们只能以当前值累加每一个子节点在不选的情况下的值。
不选:初始值为0,接着以当前节点最大值为每一个子节点选和不选这两种情况的最大值累加上当前值。
题目的答案为根节点选或不选两者之间的最大值。

代码实现如下:

#include <bits/stdc++.h>
using namespace std;
int sum,n,s;
int pre[100001],now[100001],son[100001],v[100001],m[20001];
bool pp[50001];
int f[100000][3];//此数组代表当前值的两种情况:0为不选,1为选
void tot(int a,int b) {
	pre[++sum]=now[a];
	now[a]=sum;
	son[sum]=b;
}//还原这棵树
void dfs(int u) {
	pp[u]=1;
	for(int i=now[u]; i; i=pre[i]) {
		int k=son[i];
		if(!pp[k]) {
			dfs(k);
			f[u][1]+=f[k][0];//选的情况
			f[u][0]+=max(f[k][0],f[k][1]);//不选的情况
		}
	}
	f[u][1]+=v[u];//再此节点加上选的情况的值
}
int main() {
	int a,b,ans;
	scanf("%d",&n);
	for(int i=1; i<=n; i++)
		scanf("%d",&v[i]);
	while(1) {
		scanf("%d%d",&a,&b);
		if(a==0&&b==0)
			break;
		tot(b,a);
		m[a]++;
	}
	for(int i=1; i<=n; i++)
		if(m[i]==0) {
			s=i;//找出根节点
			break;
		}
	dfs(s);
	cout<<max(f[s][1],f[s][0])<<endl;//得出答案
	return 0;
}

第七篇优快云,有不当之处请见谅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值