前置知识:并查集的基本操作
基础并查集
并查集有两个基本操作,find与merge
通过路径压缩和按秩合并(启发式合并)来减小时间复杂度
1 | void find(int x) |
种类并查集
上述并查集可以维护集合之间的关系,如朋友的朋友是朋友,但如果我们引入敌人的关系,且敌人的敌人是朋友,无法用该并查集维护
类似于2-SAT,我们将第i个节点拆成i和i+n两个节点,x与y+n同属一个集合表示x与y是敌人
假设三个点,1和2是敌人,2和3是敌人
则1与3通过2+3相连,属于同一个集合,即朋友
带权并查集
并查集中的点、边带权值时,便使用带权并查集,通常使用val[i]来存储i到其父节点路径上的权值和,用size[i]维护i作父节点时,其集合节点总数
模板题:https://www.luogu.com.cn/problem/P1196
1 | int init(int n) |
find中,在路径压缩的同时,更新val[x]的值(新的val值为其旧父节点的新val值+其到旧父节点的val值)