P1892. 团伙
考点
- 扩展域并查集
题解
1 |
|
思路
典型的扩展域并查集
每个人都有两种关系属性,我的朋友和我的敌人,所以fa数组应该多开一倍
1 ~ n的范围存储我的朋友这一关系,n + 1 ~ 2n的范围存储我的敌人这一关系
题目给了两个关系传递要求:
朋友的朋友是朋友
p和q直接合并即可敌人的敌人是朋友
对于
p而言,它的敌人关系对应p + n,那么q应与p + n同处一集合同样的,对于
q而言,它的敌人关系对应q + n,那么p应于q + n同处一集合考虑以下样例:
E 1 2
E 2 6
设字符{}代表同一集合,根据上述描述有:
{1+n, 2}、{2+n, 1}、{2+n, 6}、{6+n, 2}
是满足题目要求的
这里还有一个小Trick,合并的时候应让朋友关系设置为敌人关系的祖先,而不能颠倒:
1 | join(q + n, p), join(p + n, q); |
两者颠倒从效果上看并不会有差异,无论怎样二者都将同处一集合
但朋友关系设为敌人关系的祖先,最终统计连通块个数会更方便,只需一次遍历判断fa[i] == i即可