带权并查集理解

前言:这几天做了几个带权并查集的问题,看了网上的大量博客,也有自己的一些理解,特地总结一下。


回顾

理清理论的发展历史有助于了解理论,因此我们先回顾一下普通的并查集。戳这里.和这里,感谢博主带我入门

  • 这里有几个值得注意的地方(也是个人做题中踩过的坑)。
    • 在包含路径压缩算法的, 调用find_father(x)后,x所在集合不一定全压缩成了两层,只有xroot的路被压缩了。如图:
      带权并查集理解

带权并查集题型特点。

  • 带权并查集问题一般是让人推理两个实体间的关系。
    • 1、问题给出了实体间的一系列现有关系
    • 2、问题给出了关系的推理方式
    • 3、可以通过两个实体和父节点之间的关系推理两个节点之间的关系。
  • 解题重点
    • 1、定义合理的r[i]表示节点i与其所在集合root节点之间的关系。
    • 2、数学表达式刻画路径压缩时节点和新的父节点关系的更新。
    • 3、数学表达式刻画集合合并时,两个集合父节点之间关系的确定。

例题:

Bug’s Life

题目链接
题目大意:给出一系列昆虫间的交配关系,昆虫只有雄和雌,问是否可能存在同性交配的情况。
看看问题背景:

  • 1、首先该问题给出了一系列现有关系(交配关系).
  • 2、问题给出了关系推理方式同同为同,异异为同,同异为异
  • 3、我们只需要记录ab和父节点的关系,就可以直接推出ab的关系。
    若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只隔着一层。如图:
      带权并查集理解

所以当节点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是异性三个条件更新fafb的关系r[fa]呢.
    • 很明显,当采用亦或刻画关系时, 我们可以更具这个式子更新
      r[fa] = r[b]^1^r[a]
    • 当采用,当采用相加模2时,采用这个式子
      r[fa] = (r[b] + 1 + r[a]) % 2

食物链

题目链接

  • 看看问题背景。
    • 1、给出了一系列现有关系(谁吃谁,谁是谁的同类)
    • 2、给出了关系推理方式,三个种类形成一个环形食物链.
    • 3、以父节点为参照,可以推出两个实体的食物链关系.

若>好表示吃, =表示同类, <小于表示被吃

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).

ps:网上说可以使用向量思维,思考了很久,个人感觉这只是一个窍门,并没有办法证明出向量法的正确性。严格来说还是的枚举,不过做题时可是先试试向量思维