您的位置:首页 > 其它

【bzoj1149】 [CTSC2007]风玲Mobiles

2016-05-14 10:47 357 查看
题目意为:给一颗二叉树,每一次操作可以交换该子树的左右两颗子树,要将该树变为完全二叉树,求最小操作次数。
从根开始进行一遍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。那么当两颗子树都不满足这个条件时即为无解

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

#define N 200010

struct Node
{
int l,r,deep,data;
}tr[N<<1];

int n,m;
int l,r,depl,depr;
int ans;

int a
;

void dfs(int k)
{
if (ans==-1)
return ;
if (tr[k].l!=-1)
dfs(tr[k].l);
if (tr[k].r!=-1)
dfs(tr[k].r);
if (ans==-1)
return ;
if (tr[k].l!=-1)
l=tr[tr[k].l].data;
else
l=1;
if (tr[k].r!=-1)
r=tr[tr[k].r].data;
else
r=1;
if (l==1)
depl=1;
else
depl=tr[tr[k].l].deep;
if (r==1)
depr=1;
else
depr=tr[tr[k].r].deep;
if ((abs(depl-depr)>1) || (!a[l] && !a[r] && l!=1 && r!=1))
{
ans=-1;
return ;
}
else if (l<r)
ans++;
tr[k].deep=max(depl,depr)+1;
tr[k].data=l+r;
}

int main()
{
scanf("%d",&n);
for (int i=1;i<=200000;i<<=1)
a[i]=1;
for (int i=1;i<=n;i++)
scanf("%d%d",&tr[i].l,&tr[i].r);
dfs(1);
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: