最大子树和 (树形dp)

最大子树和

题目链接

题目描述

小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题。一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题。于是当日课后,小明就向老师提出了这个问题:
一株奇怪的花卉,上面共连有N 朵花,共有N−1条枝干将花儿连在一起,并且未修剪时每朵花都不是孤立的。每朵花都有一个“美丽指数”,该数越大说明这朵花越漂亮,也有“美丽指数”为负数的,说明这朵花看着都让人恶心。所谓“修剪”,意为:去掉其中的一条枝条,这样一株花就成了两株,扔掉其中一株。经过一系列“修剪“之后,还剩下最后一株花(也可能是一朵)。老师的任务就是:通过一系列“修剪”(也可以什么“修剪”都不进行),使剩下的那株(那朵)花卉上所有花朵的“美丽指数”之和最大。
老师想了一会儿,给出了正解。小明见问题被轻易攻破,相当不爽,于是又拿来问你。

输入格式

第一行一个整数N(1≤N≤16000)。表示原始的那株花卉上共N朵花。

第二行有N个整数,第I个整数表示第I朵花的美丽指数。

接下来N−1行每行两个整数a,b,表示存在一条连接第a 朵花和第b朵花的枝条。

输出格式

一个数,表示一系列“修剪”之后所能得到的“美丽指数”之和的最大值。保证绝对值不超过2147483647

输入案例

7
-1 -1 -1 1 1 1 0
1 4
2 5
3 6
4 7
5 7
6 7

输出案例

3

题目大意

有很多花在不同的枝干上,每个花都有权值,可以剪去丑花或者整个丑枝干减去,使整体的花枝美丽指数最大.

算法分析

树形dp,每次遍历判断当前f[i]是否为正,如果正就加上,得到最大值;

代码实现

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<map>
#include<set> 
#include<string>
#include<stack>
#include<queue>
#include<vector>
#include<math.h> 
#define inf 0x3f3f3f3f
using namespace std;
typedef long long int ll;
const int maxn=1e5+5;
struct edge
{
	int pre,to;
}e[maxn];
//e[i].pre表示与第i条边同起点的上一条边; 
//e[i].to表示第i条边的终点
int head[maxn],sum=0;//head数组记录该i点的最后一条关联边
int f[maxn],a[maxn];//f数组为当前到i的美丽指数的和,a数组为单个权值 
int cnt=0;
void add(int x,int y)//链式前向星存图 
{
	e[++cnt].pre=head[x];
	e[cnt].to=y;
	head[x]=cnt;
} 
void dfs(int sx,int fx)//dfs遍历图 
{
	f[sx]=a[sx];//每个枝节都带本身的结点权值
	for(int i=head[sx];i;i=e[i].pre)
	{
		int s=e[i].to;
		if(s!=fx)//没有到达终点的话继续递归遍历 
		{
			dfs(s,sx);
			f[sx]+=max(0,f[s]);//除去负数(不好看的丑花) 
		}
	}
	sum=max(sum,f[sx]);//更新最大值 
}
int main()
{
	int N,q;
	cin>>N;
	for(int i=1;i<=N;i++)//存权值
	{
		cin>>q;
		a[i]=q;
	}
	int a,b;
	for(int i=1;i<=N-1;i++)//n个点n-1条边
	{
		cin>>a>>b;
		add(a,b);//无向边,两个点都存一下 
		add(b,a);
	}
	dfs(1,0);//fx取0是为了遍历所有的边; 
	cout<<sum<<endl; 
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值