ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LOJ #3343. 「NOI2020」超现实树

2022-07-21 17:04:38  阅读:162  来源: 互联网

标签:rt ch NOI2020 LOJ 3343 back tot int check


提交记录

题目叙述

二叉树,称一棵树可以长成另外一颗树,当且仅当可以通过替换这棵树的叶子节点为随便其他的树,变成另一棵树。给定一个树的集合,判断是否可以只有有限棵树凑不出。

题解

考虑暴力怎么写,判断 \(i\) 的子树的所有情况是不是几乎完备的。然后只要判断左儿子和右儿子是不是几乎完备的。但是发现左儿子右儿子都有的情况下,好像就寄了。我们没有任何办法递归为一个规模不大的子问题。那咋办呢?

定义:称一棵树为好的,当且仅当这棵树一个点左儿子或者右儿子大小 \(\le 1\) 。

定理:只要凑不出来的好树有限,那么整个集合就是几乎完备的。

证明:假设深度 \(\ge x\) 的好树都可以被凑出。容易发现存在这样的 \(x\) 。对于任意树,都存在一个与他深度相同的好树可以凑出他。所以就证明完了。

因此,只要看所有好树是否能够凑出就可以了。很明显不是好树的树一定长不出好树。而我们发现好树是不是只有有限个凑不出是容易判断的,因为不存在那种,两边需要同时向下递归的情况。

总结

  • 问题不能一上来就认为解决不了。就像我开始直接认为必须两边同时向下递归一样。然而想到这样好树的定义,是不容易的。
  • 大胆猜测这种结论。

代码

#include <cstdio>
#include <iostream>
#include <vector>
#define macro_expand(x) #x
#define print_macro(x) printf("%s\n",macro_expand(x))
#define FOR(i,l,r) for(int i=(l),i##ADJK=(r);i<=i##ADJK;++i)
#define ROF(i,r,l) for(int i=(r),i##ADJK=(l);i>=i##ADJK;--i)
using namespace std;
typedef long long LL;
const int MN=2e6+5;
int ch[MN][2];
bool siz1(int u){return (!ch[u][0])&&(!ch[u][1]);}
bool check(vector<int> rt){
	if(rt.empty())return 0;
	vector<int> a,b,c,d;
	for(int i:rt){
		if(siz1(i))return 1;
		else if(ch[i][0]==0)a.push_back(ch[i][1]);
		else if(ch[i][1]==0)b.push_back(ch[i][0]);
		else{
			if(siz1(ch[i][0]))c.push_back(ch[i][1]);
			if(siz1(ch[i][1]))d.push_back(ch[i][0]);
		}
	}
	return check(a)&&check(b)&&check(c)&&check(d);
}
int main(){
	freopen("surreal.in","r",stdin);
	freopen("surreal.out","w",stdout);
	int T=0;
	scanf("%d",&T);
	while(T--){
		int M=0;scanf("%d",&M);
		int tot=0;
		vector<int> rt;
		FOR(i,1,M){
			int N=0;scanf("%d",&N);
			rt.push_back(tot+1);
			FOR(j,1,N){
				scanf("%d%d",&ch[j+tot][0],&ch[j+tot][1]);
				if(ch[j+tot][0])ch[j+tot][0]+=tot;
				if(ch[j+tot][1])ch[j+tot][1]+=tot;
			}
			tot+=N;
		}
		if(check(rt))printf("Almost Complete\n");
		else printf("No\n");
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

标签:rt,ch,NOI2020,LOJ,3343,back,tot,int,check
来源: https://www.cnblogs.com/YouthRhythms/p/16502566.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有