并查集

目录

并查集三步走

并查集,开始的时候大家都是孤岛,根节点就是自己,然后我们不断地合并、修改指针,直到所有边都访问到。

  1. 数组初始化,每个节点的 parent 指针都指向自己。数组 roots 存放所有节点的祖先节点(根节点,路径压缩)【如果要求子集中元素数量,那么还要再创建一个 counts 数组,存储一份子集元素中的数量,需要在 union 中更新】。
  2. 根据所有相连的边,不断地进行查找、合并。
  3. 查找用递归、同时能修改查找路径上的所有节点的 parent 指针,合并前先调用查找然后看是否同一子图,是则合并失败,不是则直接将 parent 指针修改一下即可。

**有向图是否有环?**拓扑排序 DAG !

**无向图是否有环?**并查集!

关于求子集的个数、子集中元素的个数,可以试试把问题转化为图的问题,那么就可以转化为子图的数目、子图中元素数目,应用图的搜索、并查集等!

Java 代码

public class UFC {
  
  private int[] roots;
  
  public UFC(int n) {
    // 并查集用数组存parent
    roots = new int[n];
    // 开始时都是孤岛,根节点的parent都指向自己
    for (int i = 0; i < n; i++) {
      roots[i] = i;
    }
  }
  
  // find 查找是递归
  public int findRoot(int i) {
    // 根节点一定指向自己
    if (roots[i] == i) return i;
    roots[i] = findRoot(roots[i]);
    return roots[i];
  }
  
  // union 合并改指针
  public boolean union(int i, int j) {
    int rootI = findRoot(i);
    int rootJ = findRoot(j);
    if (rootI == rootJ) return false;
    // 把根节点的parent指针直接更改
    roots[rootI] = rootJ; 
    return true;
  }
}
comments powered by Disqus

相关文章

GORM 自动填充 UUID 的 2 种方式

使用 uuid 库手动生成 采用这个库:github.com/gofrs/uuid 在 GORM 中定义一个 BaseModel,并增加钩子函数: import "github.com/gofrs/uuid" type BaseModel struct { ID uuid.UUID CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` EffectiveTime *time.Time } func (m *BaseModel) BeforeCreate() (err error) { m.ID, err = uuid.NewV4() if err != nil { log.Logger.Err(err).Msg("uuid create failed") return fmt.Errorf("uuid create

阅读更多

Snapcast 多房间音频控制一体化

动机 想要手头的两台 MBP 能同时无延迟播放音频,拒绝使用直播流的形式。 主旨 Vmware Ubuntu 中安装 snapserver 接受 Airplay 的信号 sudo apt install snapserver sudo apt install -y shairport-sync sudo systemctl disable --now shairport-sync 该虚拟机网络采用桥接方式 注意该服务会自动启动,你可能需要设置下配置文件位置 sudo vi /lib/systemd/system/snapserver.service

阅读更多

用 Beancount 复式记账,Double-Entry!

🤔动机 已经有很多次记账的尝试,包括各种 App 如圈子账本(现已倒闭下架)等。但有几个痛点还没法解决: 大多数都是简单的记载收支,这对手握多个银行账户、信用卡等的我来说,显得不够用 数据安全问题,数据在服务提供者

阅读更多