并查集

并查集

普通并查集

基本操作

①初始化
void init(){
   for(int i=1;i<=50000;i++)
        fa[i]=i;
}
②查询操作
int Find(int x){
    return fa[x]==x?x:Find(f[x]);
}
③集合合并
void merge(int x,int y){
  int fx=Find(x);
  int fy=Find(y);
  if(fx!=fy)
      fa[fx]=fy;
}

优化

①路径压缩
/*递归形式*/(可能会溢出栈)
int Find(int x){
    return fa[x]==x?fa[x]:Find(fa[x]);
}
/*迭代形式*/

int Find(int x) {
    int fx = x, t;
    while (fa[fx] != fx) fx = fa[fx];//找到祖先fx
    while (x != fx) { t = fa[x]; fa[x] = fx; x = t; } //路径压缩
    return fx;
}
②按秩合并(可以保留树的结构)

rk[i]秩可以理解为树高,按秩合并即在进行合并操作时让秩小的树的树根依附到秩大的树的树根上

/*rk初始化为0*/
void merge(int x,int y){
  int fx=Find(x);
  int fy=Find(y);
  if(fx!=fy){
      if(rk[fx]<rk[fy])   fa[fx]=fy;
      else if(rk[fy]<rk[fx])  fa[fy]=fx;
      else fa[fx]=fy,rk[fy]++;//相等则随便合并,但树高会增加
  }
}

rk[i]秩可以理解为节点,按秩合并即在进行合并操作时让秩小的树的树到秩大的树上

void merge(int x,int y)
{
    int fx=Find(x),fy=Find(y);
    if(fx==fy)
        return;
    if(rk[fx]>rk[fy])
        swap(fx,fy);
    fa[fx]=fy;
    rk[fy]+=rk[fx];
}

带权并查集

在普通并查集的基础上加上一个数组w来记录点与父节点之间的关系。

因此要改变查询和合并函数的写法。(常用取模的方式来更新权值)

在这里插入图片描述

如图中,如果进行合并操作,那么w[fx]+w[x]=r+w[y],即w[fx]=r+w[y]+~w[x];

查询操作
int Find(int x){
   if(fa[x]==x)
       return x;
    int fx=Find(f[x]);
    //更新w[x]的值
    return fa[x]=fx;
}
集合合并
void merge(int x,int y){
  int fx=Find(x);
  int fy=Find(y);
  if(fx!=fy)
  { fa[fx]=fy;
    //更新w[fx]的值
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值