Description
Input
Output
输出仅包含一个整数。表示最少需要多少次交换能使风铃满足Ike的条件。如果不可能满足,输出-1。
Sample Input
6
2 3
-1 4
5 6
-1 -1
-1 -1
-1 -1
Sample Output
2
题目大意:给定一棵完全二叉树,可以交换某个节点的左右儿子,求最少交换多少次数,可以使所有的叶节点深度相差不超过1,且深度较大的叶节点都在深度较小的叶节点左侧。
题解:
无解的情况好多……
首先,最大和最小的节点深度超过1就无解了。其次,如果最大深度和最小深度节点分别在一颗子树的左子树和右子树中,也是无解的。
因此,只要先做一遍DFS预处理出节点深度的有关数据,再dp就好了,注意分类就行了。
代码如下:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#define ll long long
#define inf 0x7f7f7f7f
using namespace std;
int n,l[],r[],ans,minn=inf,maxx;
void dfs(int u,int dep)
{
if(u==-)
{
maxx=max(maxx,dep);
minn=min(minn,dep);
return ;
}
dfs(l[u],dep+);dfs(r[u],dep+);
return ;
}
int work(int u,int dep)
{
int x=,y=;
if(u==-)
{
if(dep==minn) return ;
return ;
}
x=work(l[u],dep+),y=work(r[u],dep+);
if((x== && y==) || (x== && y==) || (x== && y==)) ans++;
if(x== && y==){puts("-1");exit();}
return (x|y);
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d%d",&l[i],&r[i]);
dfs(,);
if(maxx-minn>) return puts("-1"),;
if(maxx==minn) return puts("0"),;
work(,);
printf("%d\n",ans);
return ;
}