sgu143:Long Live the Queen

题意:

    有n(n<=16000)个小镇,每两个小镇有且仅有一条路径相连。每个小镇有一个收益x(-1000<=x<=1000).
    现在要求,选择一些小镇,满足下面两点要求:
    1.选择的小镇都能互相到达,并且路径上的小镇也被选择了.
    2.选择的小镇的收益和最大.

输入

   一个整数n,接下来n个整数,代表这n个小镇的收益.
   接下来n-1行,每行两个整数代表这两个小镇有道路直接相连.

输出

   一个整数,代表最大的收益

Sample Input

5
-1 1 3 1 -1
4 1
1 3
1 2
4 5

Sample Output

4
嗯,这是棵树,然后我们可以乱搞了...
首先建一棵树。注意题目中指的是选一堆点,而不是一条路径上的所有点。
记录max1[i]为以i为根结点的子树下的最大解,max2[i]为以i为根节点的子树下过结点i的最大解。
max1初始值为最小值(INF),max2[i]初始值为v[i](因为必须要过结点i)。
然后dfs,max2[i]=Σmax2[k](i->k,max2[k]>=0),max1[i]=max{max1[k],max2[i]}(i->k)。因为以i为根结点子树中的最大解只可能在它儿子的子树中或过i的最大解中。
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 16005, INF = -(1<<30);
vector<int> e[MAXN];
int n = 0, v[MAXN] = {0};
int max1[MAXN] = {0}, max2[MAXN] = {0};
int vis[MAXN] = {0}, top = 0;

void dfs(int cur)
{
	int sum = 0;
	vis[cur] = ++top;
	for(int i = 0, lim = e[cur].size(); i < lim; ++i)
		if(!vis[e[cur][i]])
		{
			dfs(e[cur][i]);
			if(max2[e[cur][i]] >= 0) sum += max2[e[cur][i]];
			max1[cur] = max(max1[cur], max1[e[cur][i]]);
		}
	max2[cur] = max(max2[cur], sum+v[cur]);
	max1[cur] = max(max1[cur], sum+v[cur]);
}

int main()
{
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i) 
	{
		scanf("%d", v+i);
		max1[i] = INF;
		max2[i] = v[i];
	}
	for(int i = 1; i < n; ++i)
	{
		int x = 0, y = 0;
		scanf("%d%d", &x, &y);
		e[x].push_back(y);
		e[y].push_back(x);	
	}
	dfs(1);
	printf("%d", max1[1]);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值