codeforces round#509(div2) E. Tree Reconstruction

这道题目的原则很简单,就是把所有出现的x排个序,然后如果后面的比前面大就把后面的做父节点,相等就从没出现过的数字中取出一个。

怎么保证没出现过的数字足够满足相等的数字呢?其实这道题已经保证了对于任何一个数字k,子树最大值<=k的位置i不会超过k个,也就是说k放进去后面有多少个和k相等的数字,必定存在多少个没出现过且小于k的数字(在更大数字出现之前)

比如 1 2 5 3 4就有5个子树最大值小于等于5,而1 2 5 3 6 4则只有4个子树最大值小于等于5.总之就是剩余的数字肯定能把x数组里面重复的数字填满,程序里面的排序过程用桶排序代替。book数组实际上是x

#include<bits/stdc++.h>
using namespace std;
set<int> unused;
int book[1010];
int in[1010];
int tot;
int main()
{
    int n;
    scanf("%d",&n);
    bool flag=true;
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if(x>y)
          swap(x,y);
        if(y!=n)
        {
            flag=false;
        }
        book[x]++;
        in[++tot]=x;
    }
    if(!flag)
    {
        printf("NO\n");
        return 0;
    }
    int num=0;
    for(int i=1;i<n;i++)
    {
        num+=book[i];
        if(num>i)
        {
            printf("NO\n");
            return 0;
        }
    }
    printf("YES\n");
    for(int i=1;i<n;i++)
    {
        unused.insert(i);
    }
    int last=-1;
    for(int i=1;i<n;i++)
    {
        if(book[i])
        {
            unused.erase(i);
            book[i]--;
            if(last!=-1)
            {
                printf("%d %d\n",last,i);
            }
            last=i;
        }
        while(book[i])
        {
            book[i]--;
            int now=*unused.begin();
            printf("%d %d\n",last,now);
            last=now;
            unused.erase(unused.begin());
        }
    }
    printf("%d %d\n",last,n);
}

数组

猜你喜欢

转载自www.cnblogs.com/lishengkangshidatiancai/p/10166487.html