目錄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(我是說這篇博客博客