我的洛谷博客
题目大意
给出一个二叉树,判断给定的树的最大对称二叉子树的节点数
划重点部分
1.这棵树所有节点的左右子树交换,新树和原树对应位置的结构相同且点权相等
2.以节点T为子树根的一棵“子树”指的是:节点T 和它的全部后代节点构成的二叉树。
题解
当时看到这题第一反应:把这颗树直接交换,看每个点是否相等,然后,我:好像好难好麻烦,去写T3吧(T3不是更难吗???)
首先我们可以枚举答案子树的根,也就是O(n),然后在n中满足条件的所有根中,找到对称数最多的树。
判断直接去递归,没有子节点的设左右子节点为-1(其实就是题目输入)。
因为二叉树是对称的,所以只要判断每组对称点,在两个点都不是-1的情况下,只要判断两个对称点是否权值相等。如果每组对称点都相等,那么以这个节点为跟的子树就为对称二叉树。
具体操作如下:
先枚举根节点,首先根节点为1
如图,初始化cnt=1(根节点),传入递归节点<2>,<3>,即f(2,3)
因为 <2>与<3>节点权值相等,所以cnt+=2,即cnt=3
往下递归,<2>的子节点和<3>的子节点中的对应点,即f(4,7)与f(5,6)。
f(4,7)中,节点<4>与<7>权值相等,对称,cnt+=2,cnt=5
继续往下递归,发现2组对称点都为2个-1,故结构相等。
f(5,6)中,节点<5>与<6>权值相等,对称,cnt+=2,cnt=7
继续往下递归,发现2组对称点都为2个-1,故结构相等。
所以,根节点为1时,答案为7.
再去判断根为2,3,4,5,6,7,发现答案都没有根为1时大,所以此二叉树最大对称值为7
代码
#include<iostream>
#include<cstdio>
using namespace std;
struct tree{
int left,right,data;
}a[1000001],b[1000001];
int n,ans;
bool f;
int w(int x,int y)
{ if(x==-1&&y==-1)return 0;
if((x==-1||y==-1)||(a[x].data!=a[y].data))
{ f=1;
return 0;
}
return w(a[x].left,a[y].right)+w(a[x].right,a[y].left)+2;
}
int main()
{ scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i].data);
for(int i=1;i<=n;i++)
{ int x,y;
scanf("%d%d",&x,&y);
a[i].left=x;
a[i].right=y;
}
for(int i=1;i<=n;i++)
{ int x=w(a[i].left,a[i].right)+1;
if(x>ans&&!f)ans=x;
f=0;
}
printf("%d",ans);
return 0;
}
by N_mustard