目录ios
就在小蒟蒻正准备刷些\(bfs\)的题,忽然来了一位大佬,开始讲一道蓝色的\(bfs\)题git
这是一道很是很是很是厉害的题目,出自一个很是很是很是牛*的比赛。是的,就是 $NOIP_{普及组} $ (应该没人看见右下角吧 \(\Omega \omega \Omega\))数组
对称二叉树函数
给你一个二叉树,让你找出这棵树的最大对称二叉树。什么是对称二叉树呢???spa
对称二叉树就是一棵树,以根节点向下画一条垂线,根节点的左子树和右子树关于这条垂线对称(只有权值是对称的)。两棵子树不须要是对称二叉树。code
咱们能够发现,若是存在对称二叉树,那么在一层中必定存在两个点,知足两个点一个有左儿子一个有右儿子,或者都有两个孩子。而且知足两个点的权值都是相同的。根据这个结论咱们能够写出一个\(check\)函数。递归
这就是\(wxl\)大佬给咱们讲的大体思路,其余的都在代码里了get
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; int n; int son[1000050][2]; int val[1000050]; int size[1000050]; inline int read()//快速读入 { int F=1,ans=0; char c; c=getchar(); while(!isdigit(c)){if(c=='-') F=-1; c=getchar();} while(isdigit(c)){ans=ans*10+c-'0'; c=getchar();} return ans*F; } void sum_size(int u)//用来预处理size数组 { size[u]=1; if(son[u][0]!=-1)//若是有左儿子,就进行递归求出左儿子的sum值 { sum_size(son[u][0]); size[u]+=size[son[u][0]]; } if(son[u][1]!=-1)//若是有右儿子,就进行递归求出右儿子的sum值 { sum_size(son[u][1]); size[u]+=size[son[u][1]]; } } inline 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(); } sum_size(1); int ans=0; for(int i=1;i<=n;++i) if(check(son[i][0],son[i][1]))//循环求得每个对称二叉树 ans=max(ans,size[i]);//每次与找到的最大值进行比较 printf("%d",ans); }
好像很水诶233(我是说这篇博客博客