浅谈一类多重传递关系的并查集问题
首先解释一下什么叫“多种传递关系”:
普通的并查集只能维护“朋友的朋友是朋友”,而面临“敌人的敌人是朋友”的情况十分乏力,多种传递关系即指“敌人的敌人是朋友”类情况。
我们首先看这样一个问题:
我们考虑将一段区间的奇偶性转化为前缀和形式,设 \(s_i\) 表示第 \(i\) 位的前缀和,则当区间 \([l,r]\) 有奇数个时,\(s_{l-1}\) 与 \(s_r\) 奇偶性不同,有偶数个时相同,这样可以转化为一个可以并查集处理的东西。
但稍加思索我们会发现这里有多种传递关系,不是单纯的在或不在一个集合里:
-
\(i\) 与 \(j\) 奇偶性相同,\(j\) 与 \(k\) 奇偶性相同,则\(i\) 与 \(k\) 奇偶性相同。
-
\(i\) 与 \(j\) 奇偶性相同,\(j\) 与 \(k\) 奇偶性不同,则\(i\) 与 \(k\) 奇偶性不同。
-
\(i\) 与 \(j\) 奇偶性不同,\(j\) 与 \(k\) 奇偶性不同,则\(i\) 与 \(k\) 奇偶性相同。
对于这种多种传递关系问题,有两种方法。
边带权并查集
我们知道,并查集是一个树形结构,所以我们可以将边加上边权,设 \(d_i\) 为第 \(i\) 位与 \(fa_i\) 之间的边权。
对于上面的题,注意到传递关系与异或十分相似,于是有 \(d_i=0\) 时,\(i\) 与 \(fa_i\) 奇偶性相同,\(d_i=1\) 时,\(i\) 与 \(fa_i\) 奇偶性不同(反过来也行)。判断时,判断两点 \(d\) 值异或的结果是否与给出结果对应即可。(只计算两点边权的的原因是并查集缩到最简形态一定是菊花,两个边权相邻成为一条链)。
对应的,\(\operatorname{find}\) 函数也会发生一些改变:
int find(int x){
if(fa[x]==x) return x;
int fx=find(fa[x]);
d[x]^=d[fa[x]];//这里增加了一条维护边权的语句,根据情况更改
return fa[x]=fx;
}
对于两个点不在一个集合里的情况,我们往往可以通过一些手段知道两个树形结构根之间应该取的边权,仍以这一题为例,由于不在一个即合理所以这条关系默认成立,设合并的两个并查集根为 \(p\),\(q\),将 \(p\) 合并到 \(q\),即有 \(ans=d_x \operatorname{xor} d_y \operatorname{xor} d_p\),移项得 \(d_p=d_x \operatorname{xor} d_y \operatorname{xor} ans\),问题解决。
扩展域并查集
我们考虑开两个并查集,分别表示“朋友”与“敌人”关系。
对于关系不确定的两个点,我们尝试带入两个并查集,寻找合法的关系决定他们的状态。
说一下上面那道题的解法:
开两个并查集,分别代表 \(s_x\) 为奇数与 \(s_x\) 为偶数,称为奇数域和偶数域,写为 \(x_o\) 与 \(x_e\),假设目前处理 \(x\) 与 \(y\) 的关系。
若偶数个,则合并 \(x_o\),\(y_o\) 与 \(x_e\),\(y_e\)。
若奇数个,则合并 \(x_o\),\(y_e\) 与 \(x_e\),\(y_o\)。
判断合法同理。
核心就是对于多种关系开多个并查集,每个并查集维护一种关系。
个人感觉一般情况下扩展域更好想点,但经过测试还是边带权并查集更快一点(差 4ms)
边带权并查集还可以用来判断一个图是否是二分图。将一个点 \(x\) 拆为 \(x_1\) 和 \(x_2\),若连边时发现两个点 \(x_1\) 与 \(y_2\) 已经属于同一集合,则说明存在奇环,不是二分图。
更多例题
方法:扩展域并查集。
一个物种共有三重身份:作为自己(维护同类关系),作为捕食者(捕食关系),作为猎物(被捕食关系),对于每只动物 \(x\) 我们开三个域 \(x_{self},x_{hunt},x_{food}\) 分别对应上文三种关系,接下来我们来满足题面里的操作。
- 前两种矛盾关系
直接判断即可
- 同种生物关系
首先判断矛盾,如果 \(x,y\) 之间存在捕食或被捕食关系,即 \(\operatorname{find}(x_{self})=\operatorname{find}(y_{hunt}) \operatorname{or} \operatorname{find}(x_{hunt})=\operatorname{find}(y_{self})\)则出现矛盾。
两个生物相同,他们本身相同,捕食的猎物也一定相同,捕食他们的生物一定相同,所以在每个域内部合并 \(x,y\)。
- 捕食关系
仍然先判断矛盾,如果 \(y\) 吃 \(x\) 或 \(x,y\) 同种,即 \(\operatorname{find}(x_{self})=\operatorname{find}(y_{hunt}) \operatorname{or} \operatorname{find}(x_{self})=\operatorname{find}(y_{self})\)则出现矛盾。
下一步,首先根据关系可以合并 \(x_{self}\) 与 \(y_{food}\),以及 \(x_{hunt}\) 与 \(y_{self}\)。
值得注意的是,由于只有三种动物且为环形关系,所以还要合并 \(x_{food}\) 与 \(y_{hunt}\)。
本文来自博客园,作者:Aurora_Borealis,转载请注明原文链接:https://www.cnblogs.com/Aurora-Borealis-Not-Found/p/17135681.html