P1122 最大子树和

题目描述P1122 最大子树和
dp

解题思路:

找到一个边界当做树的根,对每个节点采取保留,该节点的值dp[ x ] ,为f[ x ] 和 所有相连未访问过的节点最大和
在这里插入图片描述
对A点 dp[ A ] = f[ A ] + max(-1, 0) + max(3, 0) = -2
即选择A点, 对于A相连的节点,只要是大于0,都保留
去掉 -2 保留 3

对B点 dp[ B ] = f[ B ] + max(3, 0) + max(2, 0) = 1
也就是负的dp都去掉,保留非负dp

for(int i = 0; i < son[x].size(); i++){
		s = son[x][i];
		if(!vis[s]){
			DP(s);
			dp[x] += max(0, dp[s]);
			dp[x] %= mod;
		}
	}
#include <bits/stdc++.h>
using namespace std;
const int maxn = 16e3 + 5;
const int mod = 2147483647;
int n, f[maxn], dp[maxn], ans = -1e9;
bool vis[maxn];
vector<int> son[maxn];
void DP(int x){
	vis[x] = true;
	dp[x] = f[x];
	int s;
	for(int i = 0; i < son[x].size(); i++){
		s = son[x][i];
		if(!vis[s]){
			DP(s);
			dp[x] += max(0, dp[s]);
			dp[x] %= mod;
		}
	}
	// 不知道哪些会保留  我们就记录最大的值 
	ans = max(ans, dp[x]);
}
int main(){
	cin >> n;
	for(int i = 1; i <= n; i++){
		cin >> f[i];
	}
	
	int a, b;
	for(int i = 1; i < n; i++){
		cin >> a >> b;
		son[a].push_back(b);
		son[b].push_back(a);
	}
	
	//找出一个边界 当作树的根节点 
	int edge;
	for(int i = 1; i <= n; i++){
		if(son[i].size() == 1){
			edge = i;
			break;
		}
	}
	DP(edge);
	cout << ans << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值