Time Limit: 1000MS Memory limit: 65536K
题目描述
给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。
图1
图2
现给定两棵树,请你判断它们是否是同构的。
输入
注意:题目保证每个结点中存储的字母是不同的。
输出
示例输入
8 A 1 2 B 3 4 C 5 - D - - E 6 - G 7 - F - - H - - 8 G - 4 B 7 6 F - - A 5 1 H - - C 0 - D - - E 2 -
示例输出
Yes
提示
来源
示例程序
#include<stdio.h>
struct node
{
char Element;
int left;
int right;
}T1[10],T2[10];
int CreatT(struct node T[],int N)
{
int Root=-1;//假设根节点(不存在)
char cl,cr,a[10],b[10],c[10];
int check[10];
if(N)
{
int i;
for( i=0;i<N;i++)
check[i]=0;//标记该点是否为其他点的孩子
//,=1时表示在孩子中出现过,
for(i=0;i<N;i++)//=0,表示从未出现
{
scanf("%s%s%s",a,b,c);
T[i].Element=a[0]; //gen
cl=b[0];
cr=c[0];
if(cl!='-')
{
T[i].left=cl-'0';//转变换成字符对应的ASCII值
check[T[i].left]=1;//在左孩子中出现过
}
else
T[i].left=-1; // 左孩子为空
if(cr!='-')
{
T[i].right = cr-'0';
check[T[i].right] = 1;
//在右孩子中出现过
}
else
T[i].right=-1;// 右孩子为空
}
for(i=0;i<N;i++)
{
if(!check[i])//如果该点的check[i]==0 ,
{//说明该点在其他点的孩子中从未出现过,
//那么该点一定为根节点
Root=i;
break;
}
}
}
return Root;
}
int Isomorphic(int R1,int R2)
{
if((R1==-1)&(R2==-1))//两个都为空时必定同构
return 1;
else if((R1!=-1)&&(R2!=-1))//都不为空时
{
if(T1[R1].Element != T2[R2].Element)
return 0; //如果根节点就不相同,则必不同构
if((Isomorphic(T1[R1].left,T2[R2].left)&&
Isomorphic(T1[R1].right,T2[R2].right))||
(Isomorphic(T1[R1].left,T2[R2].right)
&&Isomorphic(T1[R1].right,T2[R2].left)))
return 1;//递归,左左同构或者左右同构,则同构
}
else
return 0;//其他情况,一个为空一个不为空时,不同构
}
int main()
{
int n,m;
int R1,R2;
while(scanf("%d",&n)!=EOF)
{
R1 = CreatT(T1,n);
scanf("%d",&m);
R2 = CreatT(T2,m);
if(Isomorphic(R1,R2))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}