笛卡尔树是一种特殊的二叉树,其结点包含两个关键字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
输入样例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
思路:
先把这颗树建立起来:使用二维数组dist[][]存储各个结点k1,k2的信息;使用二维数组child[][]记录左右儿子;使用一维数组dad[]记录儿子;初始化为-1
通过根节点递归进行访问各个节点,判断是否YES的条件,我用了比较笨的办法,把所有情况罗列出来;看左边所有k1数据是否比右边所有k1数据小,左边k1数据是否比父节点k1小,右边k1数据是否比父节点k1大;根节点数据k2是否比所有子结点k2小。
#include<stdio.h>
#define MAXSIZE 1010
int dist[MAXSIZE][2];//0是k1值 1是k2值
int dad[MAXSIZE];
int child[MAXSIZE][2]; //0是左孩子 1是右孩子
int vis[MAXSIZE];
int FLAG=1;
void find(int parent,int lchild,int rchild)
{
if(parent==-1)return;//递归出口
if(vis[parent]==0)//vis记录下走过的足迹,走过就不用在再了
{
vis[parent]=1;
if(lchild!=-1)
{
//左儿k1是否比父k1大?左儿k2是否比父k2小?
if(dist[parent][0]<dist[lchild][0]||dist[parent][1]>dist[lchild][1])
{
FLAG=0;
return;
}
}
if(rchild!=-1)
{
if(dist[parent][0]>dist[rchild][0]||dist[parent][1]>dist[rchild][1])
{
FLAG=0;
return;
}
}
}
int lparent=lchild;
int rparent=rchild;
int llchild=child[lparent][0];
int lrchild=child[lparent][1];
int rlchild=child[rparent][0];
int rrchild=child[rparent][1];
if(llchild!=-1&&rlchild!=-1)//左边是否比右边都要小,总共2*2四种情况
if(dist[llchild][0]>dist[rlchild][0])
{
FLAG=0;return;
}
if(llchild!=-1&&rrchild!=-1)
if(dist[llchild][0]>dist[rrchild][0])
{
FLAG=0;return;
}
if(lrchild!=-1&&rlchild!=-1)
if(dist[lrchild][0]>dist[rlchild][0])
{
FLAG=0;return;
}
if(lrchild!=-1&&rrchild!=-1)
if(dist[lrchild][0]>dist[rrchild][0])
{
FLAG=0;return;
}
find(lparent,llchild,lrchild);//递归访问
find(rparent,rlchild,rrchild);
return;
}
int main()
{
int n,i,j,root=0;
scanf("%d",&n);
for(i=0;i<n;i++)//初始化所有数据为-1
{
child[i][0]=child[i][1]=-1;
dad[i]=-1;
dist[i][0]=-1;
}//建立父子关系
for(i=0;i<n;i++)
{
scanf("%d%d%d%d",&dist[i][0],&dist[i][1],&child[i][0],&child[i][1]);
if(child[i][0]!=-1)dad[child[i][0]]=i;
if(child[i][1]!=-1)dad[child[i][1]]=i;
}
for(i=0;i<n;i++)if(dad[i]==-1)root=i;
int lchild=child[root][0],rchild=child[root][1];
find(root,lchild,rchild);
if(FLAG==1)
printf("YES\n");
else if(FLAG==0)
printf("NO\n");
return 0;
}