前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Gym - 100796C 】Minimax Tree

【Gym - 100796C 】Minimax Tree

作者头像
饶文津
发布2020-06-02 15:40:06
3750
发布2020-06-02 15:40:06
举报
文章被收录于专栏:饶文津的专栏饶文津的专栏

BUPT2017 wintertraining(15) #7FMinimax Tree

题意

给你一棵多叉树,非叶子节点中分配k个为子节点的min函数,剩下的是max函数。 现在求根节点(1)的最大值和最小值。

题解

因为最大值和最小值求法对称,以求最小值为例。

要让尽量小的上来,可以贪心选择一条路前面都是min不够了后面就用max。 因为如果min上面有max,max换到下面不会更差。

但是这条前面都是min的路选哪一条呢?显然是最后一个min节点的子节点里max取最小的。 共k个min,所以取第k+1层所有节点的max函数的最小值。

但是,如果有的叶子深度小于k,是可以直接达到的,所以要取这些叶子的最小值更新答案。

但是,如果一个节点只有一个子节点,原来认为一条路前面都选min的贪心就不成立了,如

代码语言:javascript
复制
    得到5                      得到2

    min                      min
     +                        +
     |                        |
+----+----+              +----+----+
|         |              |         |
v         v min          v         v max
5         |              5         |
          v max                    v max
          |                        |
          v max                    v max
          |                        |
          v max                    v min
          |                        |
       +--+---+                 +--+---+
       v      v                 v      v
       2      7                 2      7

把每个单子节点深度设为父节点的深度,这样就可以计算出正确答案。

代码

代码语言:javascript
复制
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100005;
const int inf = 1e9+1;
struct edge{
	int to,next;
}e[N<<1];
int cnt,head[N];
void add(int fa,int son){
	e[++cnt]=(edge){son, head[fa]};
	head[fa]=cnt;
}
int ma[N], mi[N], dma[N], dmi[N];
int n,k;
int dep[N];
int son[N];
void dfs(int x, int fa){
	dep[x]=dep[fa]+(son[fa]!=1);
	for(int i=head[x]; i; i=e[i].next){
		dfs(e[i].to, x);
		mi[x]=min(mi[x], mi[e[i].to]);
		ma[x]=max(ma[x], ma[e[i].to]);
	}
	dmi[dep[x]]=min(dmi[dep[x]],ma[x]);
	dma[dep[x]]=max(dma[dep[x]],mi[x]);
}
bool noleaf[N];
int main(){
	scanf("%d%d",&n,&k); 
	for(int i=2;i<=n;++i){
		int p;
		scanf("%d",&p);
		noleaf[p]=true;
		++son[p];
		add(p,i);
	}
	for(int i=1;i<=n;++i)dmi[i]=inf;
	int leaf=0;
	for(int i=1;i<=n;++i){
		int a;
		scanf("%d",&a);
		if(!noleaf[i]){
			mi[i]=ma[i]=a;
			++leaf;
		}else{
			mi[i]=inf;
		}
	}
	dfs(1,0);
	int	ans1=dmi[k+1], ans2=dma[n-leaf-k+1];
	for(int i=1;i<=n;++i)if(!noleaf[i]){
		if(dep[i]<k+1)ans1=min(ans1, mi[i]);
		if(dep[i]<n-leaf-k+1)ans2=max(ans2, mi[i]);
	}
	printf("%d %d", ans1, ans2);
	return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-07-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题意
  • 题解
  • 代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档