Luogu P5018対称バイナリツリー

直接問題についてあまり話さないでください= =

1.再帰

タイトルから、サブツリーはルートノードとリーフノード、またはノードのいずれかであることがわかります。タイトルの対称バイナリツリーは、ツリーの最下部までルートノードで構成される必要があるツリーです。

これは単純で、再帰的な方法を簡単に考えることができます

1.ルートノードの列挙、2つの左と右の子ノードが決定される  是否存在 と是否相等、本、と等しい権利の点は、再帰が持っている場合 。左右两个孩子节点左右两个孩子节点

上記の判断を繰り返します。

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 = 0 ;
 bool pd; // 対称バイナリツリーであるかどうかを判断する
int cnt(int x){ // xをルートノードとする対称バイナリツリーのノード数を計算する
  int sum 0 ;
   if( l [x]!= -1)合計+ =cnt(l [x]);
   if(r [x]!= -1)sum + = cnt(r [x]);
   return sum + 1 ; // ルートノードを計算する
} 

void check(int x、int y){ // 判定対称2分岐ツリー
  if(x ==- 1 && y ==- 1return ; // 最終終了
  if(x ==- 1 || y ==- 1 || v [x]!= V [y]){ // 非対称 
    pd = false ;
     return ; 
  } 
  check(l [x]、r [y]); 
  check(r [x]、l [y]); 
} 

intmain(){ 
 cin >> n;
   forint i = 1 ; i <= n; ++ i)
  cin >> v [i];
   forint i = 1 ; i <= n; ++ i)
  cin >> l [i] >> r [i]; 
  ans = 1 ; //int i = 1 ; i <= n; ++ i){ // 対称性2を列挙するための少なくとも1つの対称性(1ノード)
  フォークツリーのルートノードif(l [i]!= -1 && r [i]!= -1 && v [l [i]] == 
      pd = true ; //
     v [rの [i]]){まず、デフォルトは対称二分木
      チェック(l [i]、r [i]);
       if (pd)
    ans = max(ans、cnt(i)); // 対称二分木である場合、ノードの数を計算できます最大を取る
    } 
  } 
cout << ans;
   return  0 ; 
}
check(l [x]、r [y]); 
check(r [x]、l [y]);

対称二分木を判断するとき、それは鏡面対称でなければなりません

だからチェックするときに対称性をミラーリングする

2dfs

二分木が対称である場合同じ深さの2つのノードu vに対して、lson(u)l s o n u )およびrson(v)r s o n v )、rson(u)rが必要ですs o n u )およびlson(v)l s o n 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();
} // Add
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]]; //サイズは、次のステップに入る前に現在の状態を変更しますdfs
}
if(son [u] [1]!= -1)
{
dfs (息子[u] [1]);
サイズ[u] + =サイズ[息子[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]))
trueを返します。
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;
0を返します。
}

しかし、この爆発に近い検索は再帰ほどよくなく、私にとってはかなり難しいと思います

3.ハッシュ

ツリーの形式を直接ハッシュすることができます。つまり、中位トラバーサル1(高度な左サブツリー)と中位トラバーサル2(高度な右サブツリー)を分割してハッシュ値を記録できます。各ノードについて、ノードの左側の息子の中位トラバーサル1のハッシュ値は、右の息子の中位トラバーサル2のハッシュ値と同じです。これは、この点をルートとするツリーが対称であることを示しています(ただし、再帰的に==渡したため、ハッシュはコードにヒットしませんでした==)

おすすめ

転載: www.cnblogs.com/SKTskyking/p/12721744.html