笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2。首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大。其次所有结点的K2关键字满足优先队列(不妨设为最小堆)的顺序要求,即该结点的K2值比其子树中所有结点的K2值小。给定一棵二叉树,请判断该树是否笛卡尔树。
输入格式:
输入首先给出正整数N(≤1000),为树中结点的个数。随后N行,每行给出一个结点的信息,包括:结点的K1值、K2值、左孩子结点编号、右孩子结点编号。设结点从0~(N-1)顺序编号。若某结点不存在孩子结点,则该位置给出−1。
输出格式:
输出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;
}