码迷,mamicode.com
首页 > 其他好文 > 详细

[CF1131F] Asya And Kittens

时间:2019-03-11 13:32:58      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:int   getch   log   names   mes   ios   amp   stack   节点   

Description:

给定n个点的序列,一开始有n个块,每次将两个块合并,并告诉你这两个块中的一对元素,求一种可能的原序列

Hint:

\(n \le 1.5*10^5\)

Solution:

实在是SB题
考虑把每对点的祖先连上一个虚点,用并查集维护,最后dfs所得的树就行
为什么是对的,因为这棵树会按时间顺序由下往上合并节点
好像还有一种做法,对每个块的祖先维护一个vector表示顺序,合并时启发式合并,复杂度\(O(nlogn)\)


#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1 
#define rs p<<1|1
using namespace std;
typedef long long ll;
const int mxn=1e6+5; //空间开大点
int n,hd[mxn],f[mxn],p,cnt;
inline int read() {
    char c=getchar(); int x=0,f=1;
    while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
    return x*f;
}
inline int chkmax(int &x,int y) {if(x<y) x=y;}
inline int chkmin(int &x,int y) {if(x>y) x=y;}

struct ed {
    int to,nxt;
}t[mxn<<1];

inline void add(int u,int v) {
    t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}

inline int find(int x) 
{
    return f[x]==x?x:f[x]=find(f[x]);
}

void dfs(int u)
{
    if(u<=n) printf("%d ",u); 
    for(int i=hd[u];i;i=t[i].nxt) {
        int v=t[i].to;
        dfs(v);
    }
}

int main()
{
    n=read(); p=n; int u,v,x,y;
    for(int i=1;i<=mxn-2;++i) f[i]=i;
    for(int i=1;i<n;++i) {
        u=read(); v=read();
        x=find(u),y=find(v);
        f[x]=f[y]=++p;
        add(p,x); add(p,y);
    }
    dfs(p);
    return 0;
}

[CF1131F] Asya And Kittens

标签:int   getch   log   names   mes   ios   amp   stack   节点   

原文地址:https://www.cnblogs.com/list1/p/10509912.html

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