pat笛卡尔树

笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2。首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大。其次所有结点的K2关键字满足优先队列(不妨设为最小堆)的顺序要求,即该结点的K2值比其子树中所有结点的K2值小。给定一棵二叉树,请判断该树是否笛卡尔树。

输入格式:

输入首先给出正整数N(\le1000),为树中结点的个数。随后N行,每行给出一个结点的信息,包括:结点的K1值、K2值、左孩子结点编号、右孩子结点编号。设结点从0~(N-1)顺序编号。若某结点不存在孩子结点,则该位置给出-11

输出格式:

输出YES如果该树是一棵笛卡尔树;否则输出NO

输入样例1:

6
8 27 5 1
9 40 -1 -1
10 20 0 3
12 21 -1 4
15 22 -1 -1
5 35 -1 -1

输出样例1:

输出 YES 如果该树是一棵笛卡尔树;否则输出 NO
YES

输入样例2:

6
8 27 5 1
9 40 -1 -1
10 20 0 3
12 11 -1 4
15 22 -1 -1
50 35 -1 -1

输出样例2:

NO

K1满足二叉搜索树,但K2不满足最小堆顺序


K2满足最小堆顺序,但K1不满足二叉搜索树


K2满足最小堆顺序;K1的每个子树都满足二叉搜索树条件,但整棵树不满足二叉搜索树条件


最小N


最大N随机


///代码书写的新姿势

#include<bits/stdc++.h>
#define bug() puts("*****************");
using namespace std;
const int maxn = 1100;
int n;
int k1[maxn],k2[maxn],fa[maxn],lch[maxn],rch[maxn];

int getroot(){
	for(int i=0;i<n;i++){
		if(lch[i]!=-1) fa[lch[i]]=i;
		if(rch[i]!=-1) fa[rch[i]]=i;
	}
	for(int i=0;i<n;i++){
		if(fa[i]==-1){
			return i;
		}
	}
	return -1;
}
vector<int>vec;
void mid(int root){  //正常排序二叉树的中序序列为 有序序列 
	if(root==-1)
	return ;
	mid(lch[root]);
	vec.push_back(k1[root]);
	mid(rch[root]);
}
bool ktwo(int root){    
	if(lch[root]!=-1&&(k2[root]>k2[lch[root]]||!ktwo(lch[root]))) return false;
	if(rch[root]!=-1&&(k2[root]>k2[rch[root]]||!ktwo(rch[root]))) return false;
	return true;
}
bool judge(int root){
	if(root==-1) return false;
	mid(root);
	for(int i=1;i<vec.size();i++){  //判断中序序列是否有效 
		if(vec[i-1]>vec[i]) return false;
	}
	return ktwo(root);  //判断k2 
}
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d %d %d %d",&k1[i],&k2[i],&lch[i],&rch[i]);
	}
	memset(fa,-1,sizeof(fa));
	int root=getroot();
//	bug();
//	cout<<root<<endl;
	puts(judge(root)?"YES":"NO");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值