并查集时间复杂度

大年初一奖励自己把这段分析啃下来。

并查集结构表示

  • 令集合 \(S\) 表示并查集中所有点;
  • 令集合 \(T\) 表示所有作为根的节点。

阿克曼函数

我们定义阿克曼函数 \(A_k\) 为:

\[A_k(j)= \begin{cases} j+1, & k=0 \\ A^{j+1}_{k-1}(j), & k\ge 1 \end{cases} \]

这里,\(f^i(x)\) 表示将 \(f\) 连续应用在 \(x\)\(i\) 次,即 \(f^0(x)=x,f^i(x)=f(f^{i-1}(x))\)

再定义反阿克曼函数 \(\alpha(n)\) 为使 \(A_{\alpha(n)}(1)\ge n\) 成立的最小整数值。

势能函数定义

令每个节点维护一个值 \(\mathtt{rank}\);每个节点的初始 \(\mathtt{rank}\) 定义为 \(0\)。在合并(union)时,若两个节点的 \(\mathtt{rank}\) 不同,将 \(\mathtt{rank}\) 较小的节点合并到 \(\mathtt{rank}\) 大的节点上;否则,任意将一个节点合并到另一个节点上,并令根节点(被合并的节点)的 \(\mathtt{rank}\) 值加一;查询(find)时不对 \(\mathtt{rank}\) 进行操作。这里 \(\mathtt{rank}\) 表示每个点作为根的子树深度的一个上界。记 \(x\) 节点的 \(\mathtt{rank}\)\(r(x)\),类似地,记 \(x\) 的父节点为 \(f(x)\);总有 \(r(x)+1\le r(fa(x))\)

为了定义势函数,先定义辅助函数 \(l(x)\)

\[l(x)=\max\left(k:r(f(x))\ge A_k(r(x))\right) \]

\(r(x)\le 1\) 时,再定义 \(i(x)\) 为:

\[i(x)=\max\left(i:r(f(x))\ge A^i_{l(x)}(r(x))\right) \]

这两个函数均满足 \(x\) 不是某个树的根且 \(r(x)\gt 0\),方便起见,若 \(x\) 是某个树的根或 \(r(x)=0\),定义 \(l(x)=i(x)=0\)

显然 \(l(x)\) 随操作的进行单调不降;同时,在 \(l(x)\) 不增的情况下,\(i(x)\) 单调不降。并且:

\[\begin{aligned} 0 & \le l(x) \lt \alpha(n) \\ 1 & \le i(x) \le r(x) \end{aligned} \]

以上内容由定义显然,不证。

定义一个点 \(x\) 的势能 \(\Phi(x)\) 为:

\[\Phi(x)=(\alpha(n)-l(x))\cdot r(x)-i(x) \]

定义整个并查集 \(S\) 的势能 \(\Phi(S)\) 定义为每个节点势能的和,即:

\[\Phi(S)=\sum_{x\in S}\Phi(x) \]

容易发现,势能非负且初始状态下势能为 \(0\)

下面证明均摊复杂度。

势能变化

先考虑任意一个 \(x\not\in T\)\(r(x)>0\),设操作前势能为 \(\Phi(c)\),操作后的势能为 \(\Phi(c')\),只有三种情况:

  1. \(i(c)\)\(l(c)\) 不变。显然 \(\Phi(c)=\Phi(c')\)
  2. \(l(c)\) 不变,\(i(c)\) 增加。由于 \(i(c)\) 至少增加 \(1\),有 \(\Phi(c')\le \Phi(c)-1\)
  3. \(l(c)\) 增加,此时 \(i(c)\) 可能减少,但显然最多减少 \(r(c)-1\),而 \(l(c)\) 至少增加 \(1\),由定义可得 \(\Phi(c')\le \Phi(c)-1\)

总之,对于任意 \(x\not\in T\)\(r(x)>0\),在单次操作后势能不增;更强地,若节点 \(x\)\(i(c)\)\(l(c)\) 有变化,则操作后势能至少减 \(1\)

union(x,y) 操作

方便起见,这里假设 \(x,y\in T\)

显然所需时间为 \(\Theta(1)\),考虑其引起的势能变化。

这里假设 \(y\) 是新的根节点,即 \(r(x)\le r(y)\)

显然只有三种点的势能可能变化:

  1. 节点 \(x\)(由树根变为非树根);
  2. 节点 \(y\)\(\mathtt{rank}\) 可能增加);
  3. 操作前 \(y\) 的子节点(父节点的 \(\mathtt{rank}\) 可能增加)。

其中第三类节点在上文已经讨论过。

节点 \(x\) 由树根变为非树根,\(l(x)\)\(i(x)\) 都不会减少,故 \(\Phi(x')\le \Phi(x)\)

节点 \(y\)\(\mathtt{rank}\) 至多加一,而 \(\Phi(y)=\alpha(n)\cdot r(y)\),故 \(y\) 的势能最多增加 \(\alpha(n)\)

综上,进行 \(\mathtt{union}\) 操作后,总的势能最多增加 \(\alpha(n)\),故均摊复杂度为 \(\Theta(\alpha(n))\)

find(a) 操作

若查找路径包含 \(s\) 个节点,显然查找的时间复杂度为 \(\Theta(s)\)。只需证明总势能至少减 \(s-\alpha(n)\),即可证明均摊复杂度为 \(\Theta(\alpha(n))\)

显然任意 \(x\in T\) 的势能不变,而其他节点的势能不增,故没有节点的势能增加。

只需证明有 \(s-\alpha(n)\) 个节点的 \(l(x)\)\(i(x)\) 有改变。

\(t(x)\)\(x\) 所处的树的根节点,只需证 \(r(t(x))\ge A^{i(x)+1}_{l(x)}(r(x))\) 即可。

即:

\[r(t(x))\ge A_{l(x)}\left(A^{i(x)}_{l(x)}(r(x))\right) \]

显然只需要找到一个 \(y\)\(x\) 的祖先(且不是树根),满足 \(l(y)=l(x)\) 即可。

显然存在一些 \(x\) 不满足要求,但由于不同的 \(l(x)\) 只有 \(\alpha(n)\) 个,最多只有 \(\alpha(n)\) 个节点不满足要求。

也就是说,至少有 \(s-\alpha(n)\) 个节点的势能会改变,也即总势能至少减 \(s-\alpha(n)\)

posted @ 2025-01-29 20:25  weilycoder  阅读(61)  评论(0)    收藏  举报