题目大意:给定一棵完全二叉树,可以交换某个节点的左右儿子,求最少交换多少次可以使所有的叶节点深度相差不超过1,且深度较大的叶节点都在深度较小的叶节点左侧
铃抄千
这水题居然还WA了两次- - 脑残害死人啊QAQ
首先DFS一次处理出深度最大和最小的叶节点 如果深度相差>=2则无解
然后再DFS一遍,对于每个节点首先向子节点递归,然后记录左右两棵子树中深度较大叶节点的存在性和深度较小叶节点的存在性
如果两棵子树中都存在深度较大的叶节点和深度较小的叶节点则无解
否则讨论一下是否需要交换 如果需要交换则ans++
最后输出答案就行了- -
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
const int a[4][4]={
{0,0,0,0},
{0,0,0,0},
{0,1,0,1},
{0,1,0,0}
};
int n,ans,max_dpt,min_dpt=0x3f3f3f3f;
int ls[M],rs[M];
void DFS(int x,int dpt)
{
if(x==-1)
{
max_dpt=max(max_dpt,dpt);
min_dpt=min(min_dpt,dpt);
return ;
}
DFS(ls[x],dpt+1);
DFS(rs[x],dpt+1);
}
int Tree_DP(int x,int dpt)
{
if(x==-1)
return dpt==min_dpt?2:1;
int l=Tree_DP(ls[x],dpt+1);
int r=Tree_DP(rs[x],dpt+1);
if(l==3&&r==3)
{
cout<<-1<<endl;
exit(0);
}
ans+=a[l][r];
return l|r;
}
int main()
{
int i;
cin>>n;
for(i=1;i<=n;i++)
scanf("%d%d",&ls[i],&rs[i]);
DFS(1,1);
if(max_dpt-min_dpt>=2)
return cout<<-1<<endl,0;
if(max_dpt==min_dpt)
return cout<<0<<endl,0;
Tree_DP(1,1);
cout<<ans<<endl;
return 0;
}