不多扯题目 直接题解= =

1.递归

由题目可以得知,子树既可以是根节点和叶节点组成,也可以是一个节点,题意中的对称二叉子树是必须由一个根节点一直到树的最底部所组成的树。

这样一来就简单了,我们很容易就能想到用递归的方法

1.枚举根节点,判断其左右两个孩子节点 是否存在 以及是否相等. 若存在并且点权相等,则一直递归左右两个孩子节点左右两个孩子节点 .

重复上述判断。

2.判断好对称二叉树后,就可以计算以该节点为根节点的对称二叉子树的节点数量并取最优值了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 1e6 + 10;//习惯性用定义法 当然也可以用const
int v[N], l[N], r[N];
//v[i]:节点i权值;l[i]:编号为i的节点的左孩子的编号;r[i]:编号为i的节点的右孩子的编号
int n,ans = ;
bool pd; //判断是否为对称二叉子树
int cnt(int x) { //计算以x为根节点的对称二叉子树的节点数
int sum ;
if (l[x]!=-) sum+=cnt(l[x]);
if (r[x]!=-) sum+=cnt(r[x]);
return sum+; //算上根节点
} void check(int x, int y) { //判断对称二叉子树
if (x==-&&y==-) return ; //到底了 结束
if (x==-||y==-||v[x]!=v[y]) { //不对称
pd = false;
return;
}
check(l[x], r[y]);
check(r[x], l[y]);
} int main() {
cin>>n;
for (int i=;i<=n;++i)
cin>>v[i];
for (int i=;i<=n;++i)
cin>>l[i]>>r[i];
ans = ; //至少有一个对称(一个节点)
for(int i=; i<=n;++i) {//枚举对称二叉子树的根节点
if (l[i]!=-&&r[i]!=-&&v[l[i]]==v[r[i]]){
pd=true; //先默认为是对称二叉子树
check(l[i], r[i]);
if (pd)
ans=max(ans, cnt(i)); //如果是对称二叉子树就可以计算节点数取最大值了
}
}
cout<<ans;
return ;
}
check(l[x],r[y]);
check(r[x],l[y]);

判断对称二叉子树时,应该是镜面对称的

所以在check时直接镜面对称即可

2dfs

如果一个二叉树是对称的,那么对于深度相同的两个节点u,v,必定有lson(u)lson(u)与rson(v)rson(v),rson(u)rson(u)与lson(v)lson(v),并且val_u=val_v:

int read()
{
int x=0,f=1;
char ch=getchar();
while('0'>ch||'9'<ch){
if (ch=='-')
f=-1;
ch=getchar();
}//判断正负
while('0'<=ch<='9'){
x=x*10+ch-48;
ch=getchar();
}//纯数字相加
return x*f;
}
int n,son[1000050][2],val[1000050],size[1000050];
//son[i][0]为i的左儿子
//son[i][1]为i的右儿子
void dfs(int u) //分别从左右扫一遍
{
size[u]=1;
if(son[u][0]!=-1)
{
dfs(son[u][0]);
size[u]+=size[son[u][0]];//size进入下一步dfs前先把当前状态改变
}
if (son[u][1]!=-1)
{
dfs(son[u][1]);
size[u]+=size[son[u][1]];
}
}

bool check(int u,int v)
{
if (u==-1&&v==-1)//特判
return true;
if (u!=-1&&v!=-1&&val[u]==val[v]&&check(son[u][0],son[v][1])&&check(son[u][1],son[v][0]))
return true;
return false;
}

int main()
{
n=read();
for (int i=1;i<=n;i++)
val[i]=read();
for (int i=1;i<=n;i++)
{
son[i][0]=read();
son[i][1]=read();
}
dfs(1);
int ans=0;
for (int i=1;i<=n;i++)
if(check(son[i][0],son[i][1]))
ans=max(ans,size[i]);
cout<<ans<<endl;
return 0;
}

然而我觉得这个近乎爆搜的打法还不如递归好使而且对我来说还挺难想= =

3.hash

可以直接hash树的形态,即分中序遍历1(先进左子树)和中序遍历2(先进右子树)记录hash值,对于每一个节点,若是此节点的左儿子的中序遍历1的hash值等于右儿子的中序遍历2的hash值,说明这个点为根的树是对称的(然而我用递归通过的= =所以hash就没打代码= =)

洛谷P5018 对称二叉树的更多相关文章

  1. 洛谷P5018 对称二叉树——hash

    给一手链接 https://www.luogu.com.cn/problem/P5018 这道题其实就是用hash水过去的,我们维护两个hash 一个是先左子树后右子树的h1 一个是先右子树后左子树的 ...

  2. NOIP2018普及T4暨洛谷P5018 对称二叉树题解

    题目链接:https://www.luogu.org/problemnew/show/P5018 花絮:这道题真的比历年的t4都简单的多呀,而且本蒟蒻做得出t4做不出t3呜呜呜... 这道题可以是一只 ...

  3. 洛谷 P5018 对称二叉树(搜索)

    嗯... 题目链接:https://www.luogu.org/problem/P5018 其实这道题直接搜索就可以搜满分: 首先递归把每个点作为根节点的儿子的数量初始化出来,然后看这个节点作为根节点 ...

  4. 【洛谷P5018 对称二叉树】

    话说这图也太大了吧 这题十分的简单,我们可以用两个指针指向左右两个对称的东西,然后比较就行了 复杂度O(n*logn) #include<bits/stdc++.h> using name ...

  5. 洛谷 P5018 对称二叉树

    题目传送门 解题思路: 先计算每个点的子树有多少节点,然后判断每个子树是不是对称的,更新答案. AC代码: #include<iostream> #include<cstdio> ...

  6. 2021.08.09 P5018 对称二叉树(树形结构)

    2021.08.09 P5018 对称二叉树(树形结构) [P5018 NOIP2018 普及组] 对称二叉树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 求一棵子树,关 ...

  7. 【洛谷P5018】对称二叉树

    题目大意:定义对称二叉树为每个节点的左右子树交换后与原二叉树仍同构的二叉树,求给定的二叉树的最大对称二叉子树的大小. 代码如下 #include <bits/stdc++.h> using ...

  8. 题解 洛谷P5018【对称二叉树】(noip2018T4)

    \(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...

  9. [洛谷P1040] 加分二叉树

    洛谷题目链接:加分二叉树 题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,-,n),其中数字1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di ...

随机推荐

  1. Gradle系列之初识Gradle

    原文首发于微信公众号:躬行之(jzman-blog) 学习 Android 有一段时间了,开发中经常使用到 Gradle ,但是不知道 Gradle 构建项目的原理,计划花一点时间学习一下 Gradl ...

  2. Mycat使用配置实践

    本来写了好多,关于配置的解释和使用以及注意,但是发现有点啰嗦含金量也不高,所以直接把实际使用的一个例子放着吧,供参考. <!DOCTYPE mycat:schema SYSTEM "s ...

  3. undefined 和 not defined

    概念上的解释: undefined是javascript语言中定义的五个原始类中的一个,换句话说,undefined并不是程序报错,而是程序允许的一个值. not defined是javascript ...

  4. 【题解】LOJ2462完美的集合(树DP 魔改Lucas)

    [题解]LOJ2462完美的集合(树DP 魔改Lucas) 省选模拟考这个??????????????????? 题目大意: 有一棵树,每个点有两个属性,一个是重量\(w_i\)一个是价值\(v_i\ ...

  5. Delphi学习手记——单引号和双引号的区别

    单引号和双引号的区别 双引号表示其中字符可能包含变量,而单引号表示整个引号内的东西都当成字符串来处理. 也就是说:没有内设变量就用单引号'',有就用双引号"". 举例说明: $va ...

  6. Spark SQL源码剖析(一)SQL解析框架Catalyst流程概述

    Spark SQL模块,主要就是处理跟SQL解析相关的一些内容,说得更通俗点就是怎么把一个SQL语句解析成Dataframe或者说RDD的任务.以Spark 2.4.3为例,Spark SQL这个大模 ...

  7. Python实现按键精灵(一)-键鼠操作

    需要安装 pywin32库 pip install pywin32 import win32api import time #鼠标移动 def mouse_move(x,y): win32api.Se ...

  8. GitHub 热点速览 Vol.17:在?各家视频会员要不要?

    作者:HelloGitHub-小鱼干 摘要:经济实用,用作上周的 GitHub 热点的横批再合适不过.先不说 GitHub Trending 上不止一个的会员共享项目,免你找好友刷脸要会员,这项目实在 ...

  9. vector做形参时的三种传参方式

    vector在做形参的时候传参的方式和普通的变量是一样的,要么传值.要么传引用.要么传指针. 现在分别定义三个以vector为形参的函数: (1) fun1(vector <int> v) ...

  10. python爬虫(1)requests库

    在pycharm中安装requests库的一种方法 首先找到设置 搜索然后安装,蓝色代表已经安装 requests库中的get请求 与HTTP协议相对应,requests库也有七种请求方式. 获取ur ...