前言:这几天做了几个带权并查集的问题,看了网上的大量博客,也有自己的一些理解,特地总结一下。
文章目录
回顾
理清理论的发展历史有助于了解理论,因此我们先回顾一下普通的并查集。戳这里.和这里,感谢博主带我入门
- 这里有几个值得注意的地方(也是个人做题中踩过的坑)。
- 在包含路径压缩算法的, 调用
find_father(x)后,x所在集合不一定全压缩成了两层,只有x到root的路被压缩了。如图:
- 在包含路径压缩算法的, 调用
带权并查集题型特点。
- 带权并查集问题一般是让人推理
两个实体间的关系。- 1、问题给出了
实体间的一系列现有关系。 - 2、问题给出了
关系的推理方式。 - 3、可以通过
两个实体和父节点之间的关系推理两个节点之间的关系。
- 1、问题给出了
- 解题重点
- 1、定义合理的
r[i]表示节点i与其所在集合root节点之间的关系。 - 2、数学表达式刻画路径压缩时节点和新的父节点关系的更新。
- 3、数学表达式刻画集合合并时,两个集合父节点之间关系的确定。
- 1、定义合理的
例题:
Bug’s Life
题目链接
题目大意:给出一系列昆虫间的交配关系,昆虫只有雄和雌,问是否可能存在同性交配的情况。
看看问题背景:
- 1、首先该问题给出了一系列现有关系
(交配关系). - 2、问题给出了关系推理方式
同同为同,异异为同,同异为异。 - 3、我们只需要记录
a和b和父节点的关系,就可以直接推出a和b的关系。
若0表示同性,1表示异性
| a和父节点c关系 | b和父节点c关系 | a和b关系 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
解题重点:
- 1、定义
r[a]:为节点a和该集合父节点的关系。0表示同性,1表示异性. - 2、确定路径压缩式关系的更新方式:
- 我们知道,并查集是递归的从上向下更新的,因此在某一时刻,需要更新的节点和root只隔着一层。如图:
- 我们知道,并查集是递归的从上向下更新的,因此在某一时刻,需要更新的节点和root只隔着一层。如图:
所以当节点a所在集合父节点变化时,我们可以根据r[a]和r[fa]来更新r[a]。
| 更新前的r[a] | r[f[a]] | 更新后的r[a] |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
可以看到,我们可以根据亦或或者相加模2来刻画这样的推理逻辑。
亦或方式刻画: r[a] = r[a] ^ r[fa]相加模2方式刻画: r[a] = (r[a] + r[fa]) % 2.
- 3、确定合并集合时,父节点间关系的更新:
由于压缩路径的方式,合并集合时,一定是这样的情况。即a/b和fa/fb都是直接的父子关系。
给出了a和b是异性,我们如何更具r[a], r[b], a和b是异性三个条件更新fa和fb的关系r[fa]呢.- 很明显,当采用
亦或刻画关系时, 我们可以更具这个式子更新r[fa] = r[b]^1^r[a] - 当采用,当采用
相加模2时,采用这个式子r[fa] = (r[b] + 1 + r[a]) % 2
- 很明显,当采用
食物链
-
看看问题背景。
- 1、给出了一系列现有关系
(谁吃谁,谁是谁的同类) - 2、给出了关系推理方式,
三个种类形成一个环形食物链. - 3、以父节点为参照,可以推出两个实体的食物链关系.
- 1、给出了一系列现有关系
若>好表示吃, =表示同类, <小于表示被吃
| a和父节点c关系 | b和父节点c关系 | a和b关系 |
|---|---|---|
| a>c | b>c | b=a |
| a>c | b=c | a>b |
| a>c | b<c | b>a |
| a=c | b>c | b>a |
| a=c | b=c | b=c |
| a=c | b<c | a>b |
| a<c | b>c | a>b |
| a<c | b=c | b>a |
| a<c | b<c | b=c |
-
解题重点:
- 1、定义
r[a]: 0表示和父节点同类,1表示吃父节点,2表示被父节点吃。 - 2、确定路径压缩式关系的更新方式:
所以当节点a所在集合父节点变化时,我们可以根据r[a]和r[fa]来更新r[a]。
经过一系列枚举观察我们最终得到更新关系:r[a] = (r[a]+r[fa])%3 - 3、确定合并集合时,父节点间关系的更新:
r[fa]=(-r[a]+d-1+r[a]+3) %3。其中d表示题中给出的关系(1表示a,b为同类,2表示a吃b,更具我们的定义,我们需要将其-1).
- 1、定义
ps:网上说可以使用向量思维,思考了很久,个人感觉这只是一个窍门,并没有办法证明出向量法的正确性。严格来说还是的枚举,不过做题时可是先试试向量思维。