Yangk's 并查集-模板

Posted yangkun-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Yangk's 并查集-模板相关的知识,希望对你有一定的参考价值。

//并查集-都要给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);
    }
}

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

//可持久化并查集
/*每个版本并查集的深度不同,需要开可持久化数组记录每个版本的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;
}

 

以上是关于Yangk's 并查集-模板的主要内容,如果未能解决你的问题,请参考以下文章

带权并查集(含种类并查集)经典模板 例题:①POJ 1182 食物链(经典)②HDU - 1829 A bug's life(简单) ③hihoCoder 1515 : 分数调查(示例代码(代

Yangk's 静态主席树-模板

poj2492 A Bug's Life(带权并查集)

poj2492A Bug's Life——带权并查集

HDU1289 A Bug's Life (带权并查集)

poj2492 A Bug's Life (并查集拓展)