Codeforces Round #551 (Div. 2) D. Serval and Rooted Tree(树形dp)

题目

给定一棵n(n<=3e5)的节点的有根树,

每个节点上有一个op值,

op=0代表该点的值取子树中的min值,

op=1代表该点的值取子树中的max值,

不妨设树有k个叶子,可以将1到k共k个不重复的值填到叶子中,

使得最后根节点的值最大,输出最大值

思路来源

https://www.cnblogs.com/FrankChen831X/p/10706038.html

好题,博主讲的真是清楚明白啊QAQ

题解

Treedp的题,多画图构造样例,这样才能找到规律

树形dp,dp[i]表示在合理分配时,i能取到的i的这棵子树的第x大值,显然,dp[叶子]=1,

①当i节点为max时,显然取叶子几个值中最大的那个,也就是dp[i]最小的那个

②当i节点为min时,不妨设有两个儿子,分别取第二大和第五大,

那么由于叶子结点不重复,i只能取到第一棵子树中第二和第二棵子树中第五的较小值,

即整棵子树中第七的值,推广得,取儿子dp[j]值之和

③有了dp[1]即根的rk之后,由于共k个叶子,取第rk大,即k-rk+1

代码

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
const int INF=0x3f3f3f3f;
//dp[i]:最好情况下 i能取到i的这棵子树的从大到小第x值 
int n,num,op[N],dp[N],fa;
vector<int>E[N];
void dfs(int u,int fa)
{
	if(!E[u].size())//叶 
	{
		dp[u]=1; 
		num++;
		return;
	}
	if(op[u]==1)dp[u]=INF;//mx
	for(int v:E[u])
	{
		dfs(v,u);
		if(op[u]==1)dp[u]=min(dp[u],dp[v]);//mx
		else dp[u]+=dp[v];//mn
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	scanf("%d",&op[i]);
	for(int i=2;i<=n;++i)
	{
		scanf("%d",&fa);
		E[fa].push_back(i);
	}
	dfs(1,-1);
	printf("%d\n",num+1-dp[1]);
	return 0;
}
发布了467 篇原创文章 · 获赞 53 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/Code92007/article/details/101306416