[] NOIP対称バイナリツリー

[] NOIP対称バイナリツリー

タイトル

タイトル説明

以下の条件を玄玄を満たしている場合は、ツリーのルートの少しを持っている権利は、対称バイナリツリーと呼ばれていました:

二分木、
同じ左と交換ノードのすべてこれらの木の右サブツリー、新しいツリーと地点と等しい権利に対応する元のツリー構造。
図中の数字はIDID外側のノードはノード番号を表し、ノードの重みです。

ここに画像を挿入説明

今、私たちは、バイナリツリーを与えられて、私はあなたがそれサブツリー願って、ツリーは対称サブバイナリツリー、およびノー​​ドの最大数です。ツリー出力サブツリーノードしてください。

注意:樹木の根のみが対称バイナリツリーです。バイナリツリーノードTとその後続ノードの全て:T「サブツリー」とのサブルートノードにこの問題規則、に。

入力形式

1がルートノードである正の整数nは、ツリーの特定のノードの数、所定のノード数1〜Nの最初の行。

nは正の整数の第2行は、スペース、ノードiのi番目の正の整数の重みVIによって分離しました。次のN 2つの正の整数L_iを、R_iとの線は、各ノードiが左の子の数を表します。左/右の子は、-1手段が存在しない場合。二つの数字の間のスペースで区切られています。

出力フォーマット

総出力ファイルの行は、2つの対称的なフォークツリーノード与えられた最大ツリーを示す整数を含んでいます。

サンプル入力と出力

コピー入力#1
2
1 3
2 -1
-1 -1
出力#1のコピー
1

コピー入力#2
10
2 5 5 4 5 5 2 2 4 3
。9 10
-1 -1
-1 -1
-1 -1
-1 -1
-1 2
3 4
5 6
-1 -1
。7. 8
出力#2をコピーします
3

ここに画像を挿入説明
ここに画像を挿入説明

分析

、サンプルデータの先頭を理解していない人は、混乱少し以上に確認してください。その後、まだ読み取ることができる大規模な牛を、説明する必要があります。
さらにいくつかの質問より確認する必要があり、サンプルは彼らの最初のシミュレーションであり、それを理解するには良いです。

図1は、第1、データを読み込み、
int v[maxn],l[maxn],r[maxn]; //v权值,l左孩子编号 ,r右孩子编号
我々は最初の子は、対称程度か、子を見しようとしている場合、そのノードは、子について対称であるかどうかを確認するためにノードからトラバース開始し、その後2と
子の周りでなくなるまで、または非対称性。非対称は、その後、ルートとして2番目のノードを入れて、比較を繰り返しました。
3たびに比較的大きな値、最終的な出力

ローカルコードは疑問を持っていることがあります。

f(l[x],r[y]);					//如果该点的左右孩子对称,								
	f(r[x],l[y]);					//看该点的左右孩子的子树是否对称 

ノードID 1を持つ子どもについて、対称示すように、それは子供たちの子供の対称についてです場合、参照、
このポイントに注意を払うには、左の子の左の子と右より右の子の右の子、左と右の子のと右の子であります左よりも子供たちの子供たちは、
彼がそれを得たときに、コードを確認してください。
ここに画像を挿入説明

その他のコードは非常に詳述されています。

コード

#include<iostream>
#include<cstdio>
using namespace std;

const int maxn = 1e7;

int n;
int v[maxn],l[maxn],r[maxn];	//v权值,l左孩子编号 ,r右孩子编号 

int ans ;	//答案 
int is ; 	//是不是对称 

void f(int x,int y){		//检查是否对称 
	if(x == -1 && y == -1){				//如果没有左右孩子,return 
		return ;
	}
	if(x == -1 || y == -1 || v[x] != v[y]){	//如果不是对称 
		is = 0;								//0表示不是对称 
		return ;
	}
	f(l[x],r[y]);					//如果该点的左右孩子对称,								
	f(r[x],l[y]);					//看该点的左右孩子的子树是否对称 
}

int cnt(int x){				//累加节点数 
	int k=1;
	if(l[x] != -1 ){
		k += cnt(l[x]); 
	}
	if(r[x] != -1 ){
		k += cnt(r[x]);
	}	
	return k;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&v[i]);
	}
	for(int i=1;i<=n;i++){
		scanf("%d%d",&l[i],&r[i]);
	}
	
	//从最前的节点遍历 
	for(int i=1;i<=n;i++){
		 is = 1;		//开始先默认是对称 
		f(l[i],r[i]);	//检查是否对称 
		if(is){			//如果是对称,那就比较取较大值。 
			ans = max(ans,cnt(i));
		}
	}
	cout<<ans<<endl;
	return 0;
}
公開された75元の記事 ウォンの賞賛1 ビュー3634

おすすめ

転載: blog.csdn.net/A793488316/article/details/104744141