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[100005],r[100005],ans,minn=inf,maxx;
void dfs(int u,int dep)
{
if(u==-1)
{
maxx=max(maxx,dep);
minn=min(minn,dep);
return ;
}
dfs(l[u],dep+1);dfs(r[u],dep+1);
return ;
}
int work(int u,int dep)
{
int x=0,y=0;
if(u==-1)
{
if(dep==minn) return 1;
return 2;
}
x=work(l[u],dep+1),y=work(r[u],dep+1);
if((x==1 && y==2) || (x==1 && y==3) || (x==3 && y==2)) ans++;
if(x==3 && y==3){puts("-1");exit(0);}
return (x|y);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&l[i],&r[i]);
dfs(1,0);
if(maxx-minn>1) return puts("-1"),0;
if(maxx==minn) return puts("0"),0;
work(1,0);
printf("%d\n",ans);
return 0;
}