F. Asya And Kittens(并查集)

Asya loves animals very much. Recently, she purchased nn kittens, enumerated them from 11 and nn and then put them into the cage. The cage consists of one row of nn cells, enumerated with integers from 11 to nn from left to right. Adjacent cells had a partially transparent partition wall between them, hence there were n−1n−1 partitions originally. Initially, each cell contained exactly one kitten with some number.

Observing the kittens, Asya noticed, that they are very friendly and often a pair of kittens in neighboring cells wants to play together. So Asya started to remove partitions between neighboring cells. In particular, on the day ii, Asya:

  • Noticed, that the kittens xixi and yiyi, located in neighboring cells want to play together.
  • Removed the partition between these two cells, efficiently creating a single cell, having all kittens from two original cells.

Since Asya has never putted partitions back, after n−1n−1 days the cage contained a single cell, having all kittens.

For every day, Asya remembers numbers of kittens xixi and yiyi, who wanted to play together, however she doesn't remember how she placed kittens in the cage in the beginning. Please help her and find any possible initial arrangement of the kittens into nn cells.

Input

The first line contains a single integer nn (2≤n≤1500002≤n≤150000) — the number of kittens.

Each of the following n−1n−1 lines contains integers xixi and yiyi (1≤xi,yi≤n1≤xi,yi≤n, xi≠yixi≠yi) — indices of kittens, which got together due to the border removal on the corresponding day.

It's guaranteed, that the kittens xixi and yiyi were in the different cells before this day.

Output

For every cell from 11 to nn print a single integer — the index of the kitten from 11 to nn, who was originally in it.

All printed integers must be distinct.

It's guaranteed, that there is at least one answer possible. In case there are multiple possible answers, print any of them.

Example

input

Copy

5
1 4
2 5
3 1
4 5

output

Copy

3 1 4 2 5

Note

The answer for the example contains one of several possible initial arrangements of the kittens.

The picture below shows how the cells were united for this initial arrangement. Note, that the kittens who wanted to play together on each day were indeed in adjacent cells.

题解:可用队列模拟拼接过程,将小的接到大的后面优化时间复杂度,也可用多数组记录。

1:队列暴力版本:(注意将小的接到大的后面,否则会T哦)

#include<bits/stdc++.h>
using namespace std;
const int maxn=150010;
queue<int>q[maxn];
int f[maxn],len[maxn],n;
int getf(int x)
{
    return f[x]==x?x:f[x]=getf(f[x]);
}
void Init()
{
    for(int i=1;i<=n;i++)
    {
        f[i]=i;
        q[i].push(i);
        len[i]++;
    }
}
int main()
{
    cin>>n;
    Init();
    for(int i=1;i<=n-1;i++)
    {
        int x,y;
        cin>>x>>y;
        int t1=getf(x);
        int t2=getf(y);
        if(len[t1]<len[t2])//目的是为了把元素较少的接到元素较多的一个上
            swap(t1,t2);
        f[t2]=t1;
        len[t1]+=len[t2]; //第一个长度加上第二个长度
        len[t2]=0;         //置零
        while(!q[t2].empty())//拼接
        {
            q[t1].push(q[t2].front());
            q[t2].pop();
        }
    }
    int x=getf(1);
    while(!q[x].empty())
    {
        cout<<q[x].front()<<" ";
        q[x].pop();
    }
    return 0;
}

2:并查集+数组拼接版本: 

#include<bits/stdc++.h>
using namespace std;
const int maxn=150010;
queue<int>q[maxn];
int f[maxn],nex[maxn],pre[maxn],l[maxn],r[maxn],n;//nex存下一个,pre存上一个,l存最左边那个,r存最右边那个
int getf(int x)    //路径压缩
{
    return f[x]==x?x:f[x]=getf(f[x]);
}
void Init()
{
    for(int i=1;i<=n;i++)
    {
        f[i]=i;
        nex[i]=-1;
        pre[i]=-1;
        l[i]=r[i]=i;
    }
}
void merge_(int u,int v)
{
    u=getf(u);
    v=getf(v);
    f[v]=u;           //将v接到u后面
    nex[r[u]]=l[v];    //u的最后一个的下一个为v的最左边那个
    pre[l[v]]=r[u];     //v的最前面一个的上一个为u的最后一个
    r[u]=r[v];          //u的最后一个更新为的最后一个
                        //简而言之,这就是区间拼接,自己想想就明白了
}
int main()
{
    cin>>n;
    Init();
    for(int i=1;i<=n-1;i++)  
    {
        int x,y;
        cin>>x>>y;
        merge_(x,y);
    }
    int x;
    for(int i=1;i<=n;i++)
    {
        if(pre[i]==-1)//找到最左边的
        {
            x=i;
            break;
        }
    }
    for(int i=x;i!=-1;i=nex[i]) //依次输出
        cout<<i<<" ";
    cout<<endl;
    return 0;
}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值