[洛谷]P5018 對稱二叉樹 (#搜索)

題目描述

一棵有點權的有根樹如果滿足以下條件,則被軒軒稱爲對稱二叉樹:

  1. 二叉樹;
  2. 將這棵樹所有節點的左右子樹交換,新樹和原樹對應位置的結構相同且點權相等。

下圖中節點內的數字爲權值,節點外的 idid 表示節點編號。

現在給出一棵二叉樹,希望你找出它的一棵子樹,該子樹爲對稱二叉樹,且節點數 最多。請輸出這棵子樹的節點數。

注意:只有樹根的樹也是對稱二叉樹。本題中約定,以節點 TT 爲子樹根的一棵“子 樹”指的是:節點TT和它的全部後代節點構成的二叉樹。

輸入格式

第一行一個正整數 nn,表示給定的樹的節點的數目,規定節點編號 1 \sim n1∼n,其中節點 11 是樹根。

第二行 nn 個正整數,用一個空格分隔,第 ii 個正整數 v_ivi​ 代表節點 ii 的權值。

接下來 nn 行,每行兩個正整數 l_i, r_ili​,ri​,分別表示節點 ii 的左右孩子的編號。如果不存在左 / 右孩子,則以 -1−1 表示。兩個數之間用一個空格隔開。

輸出格式

輸出文件共一行,包含一個整數,表示給定的樹的最大對稱二叉子樹的節點數。

輸入輸出樣例

輸入 #1複製

2 
1 3 
2 -1 
-1 -1 

輸出 #1複製

1

輸入 #2複製

10 
2 2 5 5 5 5 4 4 2 3 
9 10 
-1 -1 
-1 -1 
-1 -1 
-1 -1 
-1 2 
3 4 
5 6 
-1 -1 
7 8

輸出 #2複製

3

說明/提示

【輸入輸出樣例 1 說明】

最大的對稱二叉子樹爲以節點 22 爲樹根的子樹,節點數爲 11。

【輸入輸出樣例 2 說明】

最大的對稱二叉子樹爲以節點 77 爲樹根的子樹,節點數爲 33。

【數據規模與約定】
共 2525 個測試點。
v_i ≤ 1000vi​≤1000。
測試點 1 \sim 3, n ≤ 101∼3,n≤10,保證根結點的左子樹的所有節點都沒有右孩子,根結點的右 子樹的所有節點都沒有左孩子。
測試點 4 \sim 8, n ≤ 104∼8,n≤10。
測試點 9 \sim 12, n ≤ 10^59∼12,n≤105,保證輸入是一棵“滿二叉樹” 。
測試點 13 \sim 16, n ≤ 10^513∼16,n≤105,保證輸入是一棵“完全二叉樹”。
測試點 17 \sim 20, n ≤ 10^517∼20,n≤105,保證輸入的樹的點權均爲 11。
測試點 21 \sim 25, n ≤ 10^621∼25,n≤106。

本題約定:

層次:節點的層次從根開始定義起,根爲第一層,根的孩子爲第二層。樹中任一節 點的層次等於其父親節點的層次加 11。

樹的深度:樹中節點的最大層次稱爲樹的深度。

滿二叉樹:設二叉樹的深度爲 hh,且二叉樹有 2h-12h−1 個節點,這就是滿二叉樹。

完全二叉樹:設二叉樹的深度爲 hh,除第 hh 層外,其它各層的結點數都達到最大 個數,第 hh 層所有的結點都連續集中在最左邊,這就是完全二叉樹。


思路

搜索好題,1年後的我再來這道題有了一定的思路。不斷換根找二叉樹,然後判斷是否對稱,將得到的二叉樹節點加起來,最後比較最大的節點數。實現方法用dfs。

#include <stdio.h>
#include <iostream>
#define N 1000001
using namespace std;
int l[N],r[N],a[N],s(1),n,f;
//l[i]存節點i的左兒子,r[i]存節點i的右兒子,a[i]節點i的權值 
int dfs(int x,int y,int s)//x和y是兩個節點,s爲節點總數 
{
	if(x==-1 && y==-1) return 0;//如果沒有節點就可以爬了 
	if(x==-1 || y==-1 && x!=y)//是否對稱 
	{
		f=1;
		return 0;
	}
	if(a[x]!=a[y])//是否對稱 
	{
		f=1;
		return 0;
	}
	return dfs(l[x],r[y],2)+dfs(r[x],l[y],2)+s;//爲什麼這樣寫,可以自己畫個圖理解一下。 
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	for(i=1;i<=n;i++)
	{
		cin>>l[i]>>r[i];
	}
	for(i=1;i<=n;i++)
	{
		int maxn(dfs(l[i],r[i],3));//3的原因是還要加上自己本身 
		if(maxn>s && f==0) s=maxn;
		f=0;
	}
	cout<<s<<endl;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章