并查集-模板

//并查集-都要给fa赋初值!!
//======================================
/*递归版路径压缩*/

int fa[maxn];
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
    fa[find(x)]=find(y);
}

//======================================
/*循环版路径压缩,循环稍快一点*/

int fa[maxn];
int find(int x)
{
    while(x!=fa[x]) x=fa[x]=fa[fa[x]];
    return x;
}
void merge(int x,int y)
{
    fa[find(x)]=find(y);
}

//======================================
/*按秩合并*/
/*把深度小的并到深度大的上,保证深度不会增加*/

int fa[maxn],rank[maxn];
int find(int x)
{
    return fa[x]==0?x:find(fa[x]);
}
void merge(int x,int y)
{
    x=find(x);
    y=find(y);
    if(x!=y)
    {
        if(rank[x]<=rank[y])fa[x]=y,rank[y]=max(rank[y],rank[x]+1);
        else fa[y]=x,rank[x]=max(rank[x],rank[y]+1);
    }
}

//======================================

带权并查集

int fa[maxn],val[maxn];
int find(int x)
{
    if(x!=fa[x])
    {
        int t=fa[x];
        fa[x]=find(fa[x]);
        val[x]+=val[t];
    }
    return fa[x];
}
void marage(int x,int y,int s)
{
    int px=find(x);
    int py=find(y);
    if(px!=py)
    {
        fa[px]=py;
        val[px]=-val[x]+val[y]+s;
    }
}

 

//======================================

//可持久化并查集
/*每个版本并查集的深度不同,需要开可持久化数组记录每个版本的dep
两个可持久化数组分别维护fa和dep
注意优化要选择按秩合并,不要路径压缩

1,合并a,b

2,回到第k个版本

3,询问a,b是不是在一个集合里

每次操作都算作一个版本*/

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a)&-(a))
#define clean(a,b) memset(a,b,sizeof(a))
const int mod = 1e9 + 7;
const int inf=0x3f3f3f3f;
int _;
//==================================================================
const int maxn = 2e5+9;
int tot,cnt,rootfa[maxn],rootdep[maxn],n;
struct node 
{
    int l,r,val;
}hjt[maxn*40*2];
void build(int l,int r,int &now)
{
    now=++cnt;
    if(l==r) 
    {
        hjt[now].val=++tot;
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,hjt[now].l);
    build(mid+1,r,hjt[now].r);
}
void modify(int l,int r,int var,int &now,int pos,int num)
{
    now=++cnt;
    hjt[now]=hjt[var];
    if(l==r) 
    {
        hjt[now].val=num;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid) modify(l,mid,hjt[var].l,hjt[now].l,pos,num);
    else modify(mid+1,r,hjt[var].r,hjt[now].r,pos,num);
}
int query(int l,int r,int now,int pos)
{
    if(l==r)  return hjt[now].val;
    int mid=(l+r)>>1;
    if(pos<=mid) return query(l,mid,hjt[now].l,pos);
    else return query(mid+1,r,hjt[now].r,pos);
}
int find(int var,int x)
{
    int fx=query(1,n,rootfa[var],x);
    return fx==x?x:find(var,fx);
}
void merge (int var,int x,int y)
{
    x=find(var-1,x);
    y=find(var-1,y);
    if(x==y) 
    {
        rootfa[var]=rootfa[var-1];
        rootdep[var]=rootfa[var-1];
    }
    else 
    {
        int dpx=query(1,n,rootdep[var-1],x);
        int dpy=query(1,n,rootdep[var-1],y);
        if(dpx<dpy)
        {
            modify(1,n,rootfa[var-1],rootfa[var],x,y);
            rootdep[var]=rootdep[var-1];
        }
        else if(dpx>dpy)
        {
            modify(1,n,rootfa[var-1],rootfa[var],y,x);
            rootdep[var]=rootdep[var-1];
        }
        else 
        {
            modify(1,n,rootfa[var-1],rootfa[var],x,y);
            modify(1,n,rootdep[var-1],rootdep[var],y,dpy+1);
        }
    }
}

//==================================================================
int main()
{
    int m,a,b,k,op;
    scanf("%d%d",&n,&m);
    build(1,n,rootfa[0]);
    for(int var=1;var<=m;var++)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d%d",&a,&b);
            merge(var,a,b);
        }
        else if(op==2)
        {
            scanf("%d",&k);
            rootfa[var]=rootfa[k];
            rootdep[var]=rootdep[k];
        }
        else 
        {
            scanf("%d%d",&a,&b);
            rootfa[var]=rootfa[var-1];
            rootdep[var]=rootdep[var-1];
            int x=find(var,a);
            int y=find(var,b);
            if(x==y) puts("1");
            else puts("0");
        }
    }
    return 0;
}

 

posted @ 2020-05-16 12:04  L·S·D  阅读(219)  评论(0编辑  收藏  举报