Codeforces Round #541 (Div. 2) F. Asya And Kitten 双向链表(并查集) stl之list

F. Asya And Kittens
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
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
inputCopy
5
1 4
2 5
3 1
4 5
outputCopy
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.

并查集的实质就是处理集合之间的关系,以后见到集合操作首先想一下并查集.
本题并不难 用类似并查集的算法来实现链表之间的双向查询
代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<utility>
#include<algorithm>
using namespace std;
const int maxn=150000+5;
int father[maxn];
int root[maxn];//root
int grand[maxn];//zuzhong
int ans[maxn];
int findroot(int x)//xungen
{
    if(root[x]==x) return x;
    else return root[x]=findroot(root[x]);
}
int findfather(int x)//zuzhong
{
    if(grand[x]==x) return x;
    else return grand[x]=findfather(grand[x]);
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        father[i]=i,grand[i]=i,root[i]=i;
    int tmp1,tmp2;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&tmp1,&tmp2);
        father[findfather(tmp1)]=findroot(tmp2);
        root[findroot(tmp2)]=findroot(tmp1);
        grand[findfather(tmp1)]=findfather(tmp2);
    }
    int pos=findroot(1);
    while(father[pos]!=pos)
    {
        cout<<pos<<" ";
        pos=father[pos];
    }
    cout<<pos<<endl;
}

写完之后看博客发现了大牛用list配合splice()写的代码
list函数和vector用法类似但区别有很大
list对于每次插入和删除的复杂度为o(1)而查询为o(n) vector相反
list 用法 https://blog.csdn.net/lskyne/article/details/10418823
附上

//F-STL list(双向链表)+list拼接合并 splice函数(实现并查集的操作)
/*
list的splice函数主要是用来合并两个list
splice函数是list中特有的拼接方式,splice实现了不需要拷贝的list合并,
即可以在常数时间内从list的一个区域拼接到另一个list的一个区域。
也就是说splice是一个常数时间的函数(但是也会产生其他形如list的size()问题,导致size()处理时间为O(n)不为常数)
l1.splice(l1.begin(),it);//(要插入的位置迭代器,要插入的元素的迭代器)
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=15*1e5+10;

int fa[maxn];

int find(int x)//递归并查集
{
    return x==fa[x]?x:fa[x]=find(fa[x]);
}

list<int> h[maxn];

int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){//初始化,一开始各个list里面只有自己,父节点就是自己
        h[i].push_back(i);
        fa[i]=i;
    }
    for(int i=1;i<n;i++){
        int x,y;
        cin>>x>>y;
        x=find(x);
        y=find(y);
        fa[y]=x;//并查集节点合并
        h[x].splice(h[x].end(),h[y]);//在h[x]的尾部插入h[y]
    }
    for(auto it:h[find(1)]){
        cout<<it<<" ";
    }
    cout<<endl;
}
原文地址:https://www.cnblogs.com/caowenbo/p/11852338.html