【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。那么当两颗子树都不满足这个条件时即为无解
从根开始进行一遍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; }
相关文章推荐
- openjudge7624 山区建小学
- hdoj-2099-整除的尾数
- 判断无向图是否有环
- Docker学习 ----常用操作命令大全及例子[陆续更新中...]
- word2vec (一) 简介与训练过程概要
- 如何制作纯 ASCII 文本流程图
- Python安装模块出错(ImportError: No module named setuptools)解决方法
- Android小技巧
- 街区最短路径问题
- oracle数据库的静默(Quiesce)状态
- C++重载重写重定义
- 长微博图片制作(无水印)
- AVD Manager
- 在ASP.NET 2.0中操作数据之四十三:DataList和Repeater数据排序(二)
- IDEA Java/Scala混合项目maven打包
- JAVA-反射学习(3)
- 数组------和为定值的多个数
- c++开发ocx入门实践三--基于opencv的简易视频播发器ocx
- C++——中的虚函数(Virtual function)
- 三个作业题