【18NOIP普及组】对称二叉树(信息学奥赛一本通 1981)(洛谷 5018)

摘要:
现在我们给出一个二叉树。我希望你能找到它的一个子树,这是一个节点数最多的对称二叉树。输出由一行组成,包括一个整数,表示给定树的最大对称二进制子树的节点数。2132-1-1-11最大的对称二进制子树是以节点22为根的子树,节点数为11。测试点4848,n≤ 10倍≤ 10.测试点17201720,n≤ 105亿≤ 105,并确保树点权重输入为11。测试点21252125,n≤ 106亿≤ 106.树中任何节点的层次结构等于其父节点的层次加上11.完整的二叉树:假设二叉树的深度为hh,二叉树有2h12h1个节点。这是一个完整的二叉树。

【题目描述】

一棵有点权的有根树如果满足以下条件,则被轩轩称为对称二叉树:

1.二叉树;

2.将这棵树所有节点的左右子树交换,新树和原树对应位置的结构相同且点权相等。

下图中节点内的数字为权值,节点外的idid表示节点编号。

【18NOIP普及组】对称二叉树(信息学奥赛一本通 1981)(洛谷 5018)第1张

现在给出一棵二叉树,希望你找出它的一棵子树,该子树为对称二叉树,且节点数最多。请输出这棵子树的节点数。

注意:只有树根的树也是对称二叉树。本题中约定,以节点T为子树根的一棵“子树”指的是:节点T 和它的全部后代节点构成的二叉树。

【输入】

第一行一个正整数nn,表示给定的树的节点的数目,规定节点编号1n1∼n,其中节点11是树根。

第二行nn个正整数,用一个空格分隔,第ii个正整数vivi代表节点ii的权值。

接下来nn行,每行两个正整数li,rili,ri,分别表示节点ii的左右孩子的编号。如果不存在左/右孩子,则以1−1表示。两个数之间用一个空格隔开。

【输出】

输出共一行,包含一个整数,表示给定的树的最大对称二叉子树的节点数。

【输入样例】

2
1 3
2 -1
-1 -1

【输出样例】

1

 

【样例1说明】

【18NOIP普及组】对称二叉树(信息学奥赛一本通 1981)(洛谷 5018)第2张

最大的对称二叉子树为以节点 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说明】

【18NOIP普及组】对称二叉树(信息学奥赛一本通 1981)(洛谷 5018)第3张

最大的对称二叉子树为以节点 77 为树根的子树,节点数为 33。

【数据规模与约定】

共 2525 个测试点。

vi1000vi≤1000。

测试点 131−3,n10n≤10,保证根结点的左子树所有节都没右孩子,根结点的右孩子,根结点的右子树的所有节点 都没有左孩子。

测试点 484−8,n10n≤10。

测试点 9129−12,n105n≤105,保证输入是一棵 “满二叉树 ”。

测试点 131613−16,n105n≤105,保证输入是一棵 “完全二叉树 ”。

测试点 172017−20,n105n≤105,保证输入的树点权均为 11。

测试点 212521−25,n106n≤106。

本题约定:

层次:节点的层次从根开始定义起,根为第一层,根的孩子为第二层。树中任一节点的层次等于其父亲节点的层次加11。

树的深度:树中节点的最大层次称为树的深度。

满二叉树:设二叉树的深度为hh,且二叉树有2h12h−1个节点,这就是满二叉树。

 

【18NOIP普及组】对称二叉树(信息学奥赛一本通 1981)(洛谷 5018)第4张

满二叉树(深度为 3)

 

完全二叉树:设二叉树的深度为h,除第h层外,其它各层的结点数都达到最大个数,第h层所有的结点都连续集中在最左边,这就是完全二叉树。

 

【18NOIP普及组】对称二叉树(信息学奥赛一本通 1981)(洛谷 5018)第5张

【18NOIP普及组】对称二叉树(信息学奥赛一本通 1981)(洛谷 5018)第5张

完全二叉树(深度为 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  }

免责声明:文章转载自《【18NOIP普及组】对称二叉树(信息学奥赛一本通 1981)(洛谷 5018)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇图解git基本使用hive删除空分区下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1109:开关灯

时间限制: 1000 ms 内存限制: 65536 KB 提交数: 11709 通过数: 5381 【题目描述】 假设有N盏灯(N为不大于5000的正整数),从1到N按顺序依次编号, 初始时全部处于开启状态;有M个人(M为不大于N的正整数)也从1到M依次编号。 第一个人(1号)将灯全部关闭,第二个人(2号)将编号为2的倍数的灯打开, 第三个人(3号)将编...

学习信息学奥赛,这五大的网站别忘了收藏

随着少儿编程市场的火热, 信息学竞赛也被越来越多的老师、家长、学生熟知,我收集了五个最佳的信息学竞赛的学习/刷题网站,现在分享给大家(按顺序了解更佳)。 一、NOI官网 对于程序员来说,学习一门语言最好的网站就是官网。同时对于信奥学子来说,掌握国内信息学趋势,学习信息学最好的网站自然就是NOI官网。 除了提供竞赛报名、考试大纲、最新资讯及趋势外,NOI官网...

信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1107:校门外的树

时间限制: 1000 ms 内存限制: 65536 KB 提交数: 11290 通过数: 6162 【题目描述】 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。 我们可以把马路看成一个数轴, 马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。 由于马路上有一些区域要用来建地铁。...