并查集模板

注释版:

int pre[maxn],rnk[maxn]; //rnk[a] 表示以a为根的这棵树的高度

void init(int n)
{
    for(int i=0;i<n;i++)
        pre[i]=i,rnk[i]=0;
}

int find(int x)
{
    int r=x;
    while(pre[r]!=r) r=pre[r]; //找r的前导结点 根节点的前导结点是自己,即pre[r]==r时
    int i=x,j;
    while(i!=r) //路径压缩
    {
        j=pre[i]; //记录x的前导结点
        pre[i]=r; //将i的前导结点设置为r根节点
        i=j;
    }
    rnk[r]=2;
    return r;
}

void join(int x,int y)
{
    int a=find(x); //x的根结点为a
    int b=find(y); //y的根结点为b
    if(a==b) return;
    if(rnk[a]<rnk[b]) pre[a]=b; //高度小的树接在高度更大的根节点下,那样两棵树的最大高度仍然不会变
    else
    {
        pre[b]=a;               //同理
        if(rnk[a]==rnk[b]) rnk[a]++; //如果原来高度相同,任何一棵树接在任何一个根结点下面,最大高度都会+1
    }
}

 

简洁版:

//并查集
int pre[maxn],rnk[maxn];
inline void init(int n) {for(int i=0;i<=n;i++) pre[i]=i,rnk[i]=0;}
inline int find(int x)
{
    int r=x,i=x,j;
    while(pre[r]!=r) r=pre[r];
    while(i!=r) {j=pre[i];pre[i]=r;i=j;} rnk[r]=2;
    return r;
}
inline void join(int x,int y)
{
    int a=find(x),b=find(y);
    if(a==b) return;
    if(rnk[a]<rnk[b]) pre[a]=b;
    else {pre[b]=a;  if(rnk[a]==rnk[b]) rnk[a]++;}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值