【题目描述】
一棵有点权的有根树如果满足以下条件,则被轩轩称为对称二叉树:
1.二叉树;
2.将这棵树所有节点的左右子树交换,新树和原树对应位置的结构相同且点权相等。
下图中节点内的数字为权值,节点外的idid表示节点编号。
现在给出一棵二叉树,希望你找出它的一棵子树,该子树为对称二叉树,且节点数最多。请输出这棵子树的节点数。
注意:只有树根的树也是对称二叉树。本题中约定,以节点T为子树根的一棵“子树”指的是:节点T 和它的全部后代节点构成的二叉树。
【输入】
第一行一个正整数nn,表示给定的树的节点的数目,规定节点编号1∼n1∼n,其中节点11是树根。
第二行nn个正整数,用一个空格分隔,第ii个正整数vivi代表节点ii的权值。
接下来nn行,每行两个正整数li,rili,ri,分别表示节点ii的左右孩子的编号。如果不存在左/右孩子,则以−1−1表示。两个数之间用一个空格隔开。
【输出】
输出共一行,包含一个整数,表示给定的树的最大对称二叉子树的节点数。
【输入样例】
2
1 3
2 -1
-1 -1
【输出样例】
1
【样例1说明】
最大的对称二叉子树为以节点 22 为树根的子树,节点数为 11。
【样例输入2】
10
2 2 5 5 5 5 4 4 2 3
9 10
-1 -1
-1 -1
-1 -1
-1 -1
-1 2
3 4
5 6
-1 -1
7 8
【样例输出2】
3
【样例2说明】
最大的对称二叉子树为以节点 77 为树根的子树,节点数为 33。
【数据规模与约定】
共 2525 个测试点。
vi≤1000vi≤1000。
测试点 1−31−3,n≤10n≤10,保证根结点的左子树所有节都没右孩子,根结点的右孩子,根结点的右子树的所有节点 都没有左孩子。
测试点 4−84−8,n≤10n≤10。
测试点 9−129−12,n≤105n≤105,保证输入是一棵 “满二叉树 ”。
测试点 13−1613−16,n≤105n≤105,保证输入是一棵 “完全二叉树 ”。
测试点 17−2017−20,n≤105n≤105,保证输入的树点权均为 11。
测试点 21−2521−25,n≤106n≤106。
本题约定:
层次:节点的层次从根开始定义起,根为第一层,根的孩子为第二层。树中任一节点的层次等于其父亲节点的层次加11。
树的深度:树中节点的最大层次称为树的深度。
满二叉树:设二叉树的深度为hh,且二叉树有2h−12h−1个节点,这就是满二叉树。
|
满二叉树(深度为 3)
|
完全二叉树:设二叉树的深度为h,除第h层外,其它各层的结点数都达到最大个数,第h层所有的结点都连续集中在最左边,这就是完全二叉树。
|
|
完全二叉树(深度为 3)
|
完全二叉树(深度为 3)
|
刚开始看到这道题的时候我居然傻乎乎的用指针去写!!!还邻接链表!真的够沙雕了( Ĭ ^ Ĭ )
然后在纸上写了一番后想到如果一棵二叉树的中序遍历是回文的话那就一定是对称二叉树,然鹅这道题并不是要我们判断某棵树是否为对称二叉树,而是要我们求给定的树的最大对称二叉子树的节点数!!所以我就gg了...然后脑子里一片空白,慌得一批
后来去网上看了别人的题解后觉得也不那么难嘛,直接跑暴力就能过!!ε=(´ο`*)))唉现在说什么都晚了,那个时候怎么就没想到呢
直接上代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3 const int SIZE=1000005;
4 const int INF=0x3f3f3f3f;
5 #define ll long long
6
7 struct Tree{
8 int v,Left_Child,Right_Child;
9 }tree[SIZE];
10
11 void DFS(int L,int R);
12
13 int n,sum=1,ans=1;
14 bool F=true;
15
16 int main()
17 {
18 scanf("%d",&n);
19 for (int i=1;i<=n;i++) scanf("%d",&tree[i].v);
20 for (int i=1;i<=n;i++) scanf("%d%d",&tree[i].Left_Child,&tree[i].Right_Child);
21
22 for (int i=1;i<=n;i++){
23 F=true;
24 sum=1;
25 DFS(tree[i].Left_Child,tree[i].Right_Child);
26 if (F) ans=max(ans,sum);
27 }
28
29 cout<<ans;
30
31 return 0;
32 }
33
34 void DFS(int L,int R)
35 {
36 if (F==false) return;
37 if (L==-1 && R==-1) return;
38 if ((L==-1 && R!=-1) || (L!=-1 && R==-1)){
39 F=false;
40 return;
41 }
42
43 if (tree[L].v==tree[R].v){
44 sum+=2;
45 DFS(tree[L].Left_Child,tree[R].Right_Child);
46 DFS(tree[L].Right_Child,tree[R].Left_Child);
47 }
48 else{
49 F=false;
50 return;
51 }
52 }
再来个详细点的:
1 #include<bits/stdc++.h>
2 using namespace std;
3 int v[2000001],lc[2000001],rc[2000001],cn[2000001];
4 int n,mi,nu;
5 bool f;
6 int read()
7 {
8 char c;int ff=1;
9 while((c=getchar())<'0'||c>'9')
10 if(c=='-')ff=-1;
11 int num=c-'0';
12 while((c=getchar())>='0'&&c<='9')
13 num=num*10+c-'0';
14 return ff*num;
15 }
16 int c(int i)
17 {
18 if(cn[i])return cn[i];
19 long long sum=1;
20 if(lc[i]!=-1)sum+=c(lc[i]);
21 if(rc[i]!=-1)sum+=c(rc[i]);
22 return cn[i]=sum;
23 }
24 void work(int x,int y)
25 {
26 if(x==-1&&y==-1)return;
27 if(x==-1||y==-1||v[x]!=v[y])
28 {
29 f=false;return ;
30 }
31 work(lc[x],rc[y]);
32 work(rc[x],lc[y]);
33 }
34 int main()
35 {
36 freopen("tree.in","r",stdin);
37 freopen("tree.out","w",stdout);
38 cin>>n;
39 for(int i=1;i<=n;i++)
40 v[i]=read();
41 for(int i=1;i<=n;i++)
42 {
43 lc[i]=read();rc[i]=read();
44 }
45 int ans=1;
46 for(int i=1;i<=n;i++)
47 if(lc[i]!=-1&&rc[i]!=-1&&v[lc[i]]==v[rc[i]])
48 {
49 f=true;
50 work(lc[i],rc[i]);
51 if(f)ans=max(ans,c(i));
52 }
53 cout<<ans;
54 return 0;
55 }