【bzoj1149】 [CTSC2007]风玲Mobiles

题目意为:给一颗二叉树,每一次操作可以交换该子树的左右两颗子树,要将该树变为完全二叉树,求最小操作次数。
从根开始进行一遍DFS。记录每棵子树的大小size,如果左子树的size小于右子树的size那么答案+1。实际上并不需要真的将两颗子树交换。接下来就是处理无解的情况了。
我们进行分类讨论。
  1. 由题意得树的最大深度max_deep-min_deep<=1。我们可以在DFS的过程中记录deep来实现。

  2. 判断两颗子树交换后左子树的右儿子size小于右子树左儿子size的情况。通过观察我们发现,当max_deep==min_deep时,size_left==2^n。size_right==2^k。那么当两颗子树都不满足这个条件时即为无解

 

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 using namespace std;
 8  
 9 #define N 200010
10  
11 struct Node
12 {
13     int l,r,deep,data;
14 }tr[N<<1];
15  
16 int n,m;
17 int l,r,depl,depr;
18 int ans;
19  
20 int a[N];
21  
22 void dfs(int k)
23 {
24     if (ans==-1)
25         return ; 
26     if (tr[k].l!=-1)
27         dfs(tr[k].l);
28     if (tr[k].r!=-1)
29         dfs(tr[k].r);
30     if (ans==-1)
31         return ;
32     if (tr[k].l!=-1)
33         l=tr[tr[k].l].data;
34     else
35         l=1;
36     if (tr[k].r!=-1)
37         r=tr[tr[k].r].data;
38     else
39         r=1;
40     if (l==1)
41         depl=1;
42     else
43         depl=tr[tr[k].l].deep;
44     if (r==1)
45         depr=1;
46     else
47         depr=tr[tr[k].r].deep;
48     if ((abs(depl-depr)>1) || (!a[l] && !a[r] && l!=1 && r!=1))
49     {
50         ans=-1;
51         return ;
52     }
53     else if (l<r)
54         ans++;
55     tr[k].deep=max(depl,depr)+1;
56     tr[k].data=l+r;
57 }
58  
59 int main()
60 {
61     scanf("%d",&n);
62     for (int i=1;i<=200000;i<<=1)
63         a[i]=1;
64     for (int i=1;i<=n;i++)
65         scanf("%d%d",&tr[i].l,&tr[i].r);
66     dfs(1);
67     printf("%d",ans);
68     return 0;
69 }

 

posted @ 2016-05-14 10:47  Yangjiyuan  阅读(314)  评论(0编辑  收藏  举报