码迷,mamicode.com
首页 > Windows程序 > 详细

APIO2007 风铃

时间:2018-10-19 10:17:14      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:queue   algo   using   根据   set   span   mes   char   ios   

传送门

这道题好巧妙啊……

首先根据题目大意可以知道如果有风铃的深度差值大于1的话那么肯定是不合法的,风铃的深度就可以被看成高的和低的(雾)。

然后,我们要进行交换,但是交换其实并不会改变一个节点所在的子树,也就是说,你不可能把某一个子树从树里面分裂出来再放回去,所以,如果一个节点的左右两棵子树内全都又有高风铃,又有低风铃,那么肯定是无法交换完成的。

否则的话,一共有三种情况需要我们交换:

1.左边全都是深度低的,右边全都是深度高的

2.左边全是深度低的,右边深度高低的都有

3.左边深度高低的都有,右边全是深度高的。

因为我们是递归返回的时候从下向上进行交换,所以我们可以保证在某一层进行交换的时候,子树一定是有序的,所以以上三种情况我们每次交换只要交换一次既满足情况。同时我们可以返回的时候特判不合法情况,同时返回下一层情况。我的做法是用0,1,2来表示上面三种情况,直接返回即可。

看一下代码。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar(‘\n‘)

using namespace std;
typedef long long ll;
const int M = 100005;
const int INF = 1000000009;

int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < 0 || ch > 9)
    {
    if(ch == -) op = -1;
    ch = getchar();
    }
    while(ch >= 0 && ch <= 9)
    {
    ans *= 10;
    ans += ch - 0;
    ch = getchar();
    }
    return ans * op;
}

struct node
{
    int lc,rc;
}t[M];

int n,ans,maxn = 0,minn = 100000000;
bool flag;

void dfs(int x,int depth)
{
    if(x == -1)
    {
    minn = min(minn,depth),maxn = max(maxn,depth);
    return;
    }
    dfs(t[x].lc,depth+1),dfs(t[x].rc,depth+1);
}

int solve(int x,int depth)
{
    if(x == -1) return (depth == minn) ? 0 : 1;
    int a = solve(t[x].lc,depth+1),b = solve(t[x].rc,depth+1);
    if((a == 0 && b == 1) || (a == 2 && b == 1) || (a == 0 && b == 2)) ans++;
    if(a == 2 || b == 2)
    {
    if(a == 2 && b == 2) flag = 1;
    return 2;
    }
    if(!a && !b) return 0;
    if(a + b == 1) return 2;
    if(a == 1 && b == 1) return 1;
}

int main()
{
    n = read();
    rep(i,1,n) t[i].lc = read(),t[i].rc = read();
    dfs(1,0);
    if(maxn - minn > 1) printf("-1\n");
    else if(maxn == minn) printf("0\n");
    else
    {
    solve(1,0);
    flag ? printf("-1\n") : printf("%d\n",ans);
    }
    return 0;
}

 

APIO2007 风铃

标签:queue   algo   using   根据   set   span   mes   char   ios   

原文地址:https://www.cnblogs.com/captain1/p/9814334.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!