Codeforces743D Chloe and pleasant prizes[树形DP]

博客介绍了Codeforces 743D问题的解决方案,涉及树形动态规划(DP)技术。题目要求在给定以1为根的树中找到两棵没有公共节点的子树,使它们的节点值之和最大。当树为链时,问题无解。博主通过定义cot数组存储以某个节点为根的子树节点值之和,man数组记录以该节点为根的最大子树值。最后,对于有至少两个子节点的节点,博主更新答案为当前子树的最大值与次大值之和。
摘要由CSDN通过智能技术生成

题意:给你一棵以1为根的树,问截取他的两棵子树,这两棵子树上的节点的值全加起来的最大值为多少,并且这两棵子树不能有公共的节点。如果不存在这样的两棵子树,输出"Impossible".


首先是不存在的情况,当给出的一棵树为一条链的时候就是不存在的。

然后就是如何求值,我们把选子树看成选择树上的一个节点u,那么我们就需要以u为根的树上的点值的总和,我们用一个数组cot存,其次,因为要求最大值,那么我们还需要一个man数组来表示以u为根的树的所有子树的值的最大值

得到cot数组和man数组后,我们可以对每个有两个及两个以上子节点的节点进行ans = max(ans,第一大+第二大);

具体实现见以下代码。(写完都不知道这是树形dp。。。)

#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
#define ll long long
#define INF 0x3f3f3f3f3f3f3f3f
long long n,man[maxn],cot[maxn],a[maxn],ans = -INF;
int x,y;
bool vis[maxn];
vector<int>vec[maxn];
pair<ll,ll> dfs(int u){
	pair<ll,ll>tmp;
	bool flag = 0;
	vector<ll>gao;
	for(int i=0;i<vec[u].size();++i){
		if(!vis[vec[u][i]]){
			vis[vec[u][i]]=1;
			flag = 1;
			tmp = dfs(vec[u][i]);
			gao.push_back(tmp.second);
			man[u]=max(man[u],tmp.second);
			cot[u]+=tmp.first;
		}
	}
	if(gao.size()>=2){
		sort(gao.begin(),gao.end());
		ans = max(ans,gao[gao.size()-1]+gao[gao.size()-2]);
	}
	man[u]=max(man[u],cot[u]);
	return make_pair(cot[u],man[u]);
}
int main(){
	memset(vis,0,sizeof(vis));
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%I64d",&a[i]),cot[i]=a[i],man[i]=-INF;
	for(int i=0;i<n-1;++i)scanf("%d%d",&x,&y),vec[x].push_back(y),vec[y].push_back(x);
	vis[1]=1;
	dfs(1);
	//for(int i=1;i<=n;++i)printf("%d %d\n",cot[i],man[i]);
	if(ans == -INF)printf("Impossible\n");
	else printf("%I64d\n",ans);
} 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值