【題意】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 }