【NOIP2018】對稱二叉樹

【題意】c++

編程

【解法】spa

暴力+剪枝3d

說實話一拿到題目最開始的想法是中序和中序對稱、前序和後序對稱,然而最後上手去寫之後發現這編程複雜度高到必定境界,仍是暴力拯救世界的好code

首先,怎麼斷定一棵子樹是否是對稱二叉樹blog

1 bool check(ll x,ll y)
2 {
3     if (x==-1&&y==-1) return true;  // 皆爲空
4      if (x==-1||y==-1) return false; // 一邊不爲空 
5     if (a[x]!=a[y]) return false;   // 數值不相等
6     return ((check(l[x],r[y])&&check(r[x],l[y])));
7 }

若是待斷定的子樹的根節點爲x,則只須要check(l[x],r[x])便可it

然而對每一個節點都判斷,很顯然是時間上是來不及的io

須要剪枝class

什麼狀況下徹底不可能有對稱二叉樹二叉樹

一、兩棵子樹節點數不一樣

二、兩棵子樹高度不一樣

三、兩棵子樹權值和/最大值/最小值不一樣

 1 void dfs(ll rt,ll&h,ll&sz,ll&sum)
 2 {      // 節點,高度,節點數,權值和
 3     if (rt<=0)
 4     {
 5         h=0,sz=0,sum=0;
 6         return;
 7     }
 8     ll h1,h2,sz1,sz2,sm1,sm2;
 9     dfs(l[rt],h1,sz1,sm1);
10     dfs(r[rt],h2,sz2,sm2);
11     if (h1==h2&&sz1==sz2&&sm1==sm2)
12         if (check(l[rt],r[rt]))
13             ans=max(ans,sz1+sz2+1);
14     h=max(h1,h2)+1; 
15     sz=sz1+sz2+1;
16     sum=sm1+sm2+a[rt];
17 }

實際上,只須要判斷高度+節點數就行

【代碼】

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1000000+5;
 4 typedef long long ll;
 5 ll n;
 6 ll l[N]={0},r[N]={0};
 7 ll a[N];
 8 ll ans;
 9 bool check(ll x,ll y)
10 {
11     if (x==0&&y==0) return true;  // 皆爲空 
12     if (a[x]!=a[y]) return false;
13     return ((check(l[x],r[y])&&check(r[x],l[y])));
14 }
15 void dfs(ll rt,ll&h,ll&sz)
16 {
17     if (rt<=0)
18     {
19         h=0,sz=0;
20         return;
21     }
22     ll h1,h2,sz1,sz2;
23     dfs(l[rt],h1,sz1);
24     dfs(r[rt],h2,sz2);
25     if (h1==h2&&sz1==sz2)
26         if (check(l[rt],r[rt]))
27             ans=max(ans,sz1+sz2+1);
28     h=max(h1,h2)+1; 
29     sz=sz1+sz2+1; 
30 }
31 int main()
32 {
33     scanf("%lld",&n);
34     for (int i=1;i<=n;i++)
35         scanf("%lld",&a[i]);
36     for (int i=1;i<=n;i++)
37     {
38         scanf("%lld%lld",&l[i],&r[i]);
39         if (l[i]==-1) l[i]++;
40         if (r[i]==-1) r[i]++;
41     }
42     a[0]=-1;
43     ans=1;
44     ll h,sz;
45     dfs(1,h,sz);
46     printf("%lld",ans);
47 }
相關文章
相關標籤/搜索