CodeForces1131 F.Asya And Kittens (并查集)

F.Asya And Kittens

Asya loves animals very much. Recently, she purchased n kittens, enumerated them from 1 and n and then put them into the cage. The cage consists of one row of n cells, enumerated with integers from 1 to n from left to right. Adjacent cells had a partially transparent partition wall between them, hence there were n−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 i, Asya:

Noticed, that the kittens xi and yi, 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−1 days the cage contained a single cell, having all kittens.

For every day, Asya remembers numbers of kittens xi and yi, 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 n cells.

Input

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

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

It’s guaranteed, that the kittens xi and yi were in the different cells before this day.

Output

For every cell from 1 to n print a single integer — the index of the kitten from 1 to n, 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

5
1 4
2 5
3 1
4 5

output

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.
在这里插入图片描述

思路:

知道是并查集,但是实在没想出来怎么存相邻的。

看题解发现并查集+队列+暴力启发式合并 就行了(吐血 )
因为题目n只有1.5e5,启发式合并能保证时间复杂度不爆炸

或者只用并查集,并且维护并查集代表的序列信息就行了
补完维护序列的代码之后发现和之前写的一道数组模拟链表+合并的题目基本一样,
可恶啊,太不熟练了

挂两种代码

code1:

并查集+队列+暴力启发式合并

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxm=2e5+5;
int pre[maxm];
queue<int>q[maxm];
int n;
void init(){
    for(int i=0;i<maxm;i++){
        pre[i]=i;
        q[i].push(i);//每个集合开始的时候有自己
    }
}
int ffind(int x){
    return pre[x]==x?x:pre[x]=ffind(pre[x]);
}
signed main(){
    init();
    cin>>n;
    for(int i=1;i<=n-1;i++){
        int a,b;
        cin>>a>>b;
        int x=ffind(a);
        int y=ffind(b);
        if(x!=y){
            if(q[x].size()>q[y].size())swap(x,y);//改成q[x].size()小
            pre[x]=y;
            while(!q[x].empty()){//x合并到y
                q[y].push(q[x].front());
                q[x].pop();
            }
        }
    }
    int x=ffind(1);//找到全部合并在一起的集合
    while(!q[x].empty()){//输出
        cout<<q[x].front()<<' ';
        q[x].pop();
    }
    return 0;
}
code2:

并查集+维护序列信息

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
//#define int long long
const int maxm=2e5+5;
int pre[maxm];
int nt[maxm];//相邻的下一个
int l[maxm],r[maxm];//并查集代表的序列最左边和最右边
void init(){
    for(int i=0;i<maxm;i++){
        pre[i]=i;
        l[i]=r[i]=i;
    }
}
int ffind(int x){
    return pre[x]==x?x:pre[x]=ffind(pre[x]);
}
signed main(){
    init();
    int n;
    cin>>n;
    for(int i=1;i<=n-1;i++){
        int a,b;
        cin>>a>>b;
        int x=ffind(a);
        int y=ffind(b);
        if(x!=y){//x在左y在右,合并之后为y
            nt[r[x]]=l[y];//x的最右边的下一个就是y的最多左边
            pre[x]=y;
            l[y]=l[x];//最左变为l[x]
        }
    }
    for(int i=l[ffind(1)];i;i=nt[i]){//输出
        cout<<i<<' ';
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值