支配树

安利一个讲的很好的视频:https://www.bilibili.com/video/BV1DA411k79m/?spm_id_from=333.1007.top_right_bar_window_default_collection.content.click&vd_source=4a68135b832d2f091043edf853a1e7a9

 

调整法和dfs树是图论的大杀器。

 

我们首先建立 dfs 树,这很经典。idom[x] 一定在 dfs 树上也是 x 的祖先。

 

然后考虑一个点 u 什么时候不能支配 v 。

必然是 u 子树外一点绕进子树,可以到达 (u,v] 这个树边上的一点。

 

引理:如果 x->y 存在 2 条不相交的路径,那么可以直接添加边 x->y。正确性显然。

我们希望通过这个引理加一些边。然后利用加的边,再通过一定的分析去掉一些冗余的边,相当于在对这个图做调整

 

考虑如果存在这样的一条路径,我们对它做一点调整,让他有更好的性质,方便我们分析。

  • 我们记根为 S 的话 ,一条这样的路径,必然经过 [S,u) 。因为显然从 S 出发,然后我们找到最后一次经过(不一定是dep最大)的属于 [S,u) 路径的点 x,把前面的路径全部调整为 S 直接通过树边到 x 。然后因为 x 是最后一次经过,所以以后就不经过任何 [S,u) 了,仔细一想,这个性质可以充分的推出不经过任何 dfn 序比 u 小的点了,但其实不等价。(这里 tarjan 真是聪明到极点了,我甚至想了好几遍半支配树的定义,反向推导出这个东西)
  • 反过来再分析 (u,v]。同样的方法,我们取第一次到达 (u,v] 的时候,直接从这里截断后面路径的不要了,把这个点记作 y ,实际上利用引理就可以直接加一条边 x->y (这里的x还是上面的x),你根据 "第一次到达" 这个性质是可以和上面一样的推出,x->y 上的路径上的点,去掉x和y,dfn都比 y 大!此时我们发现和 u 就没关系了,而且在 x->y 加边,可以直接否定 u 在 y 子树内的支配 ,这跟接下来半支配点的正确性有很大关系。

 

这个时候我们引入半支配点。

(定义)x 的半支配点记作 sdom[x] ,是dfn最小的可以通过 dfn 比 dfn[x] 的点来到 x 的点。(关于半支配点为什么是最小(最远),而不是像支配点一样最近,是因为半支配点的意义是用来否定支配点的)

 

半支配点可以让我们有更好感知的性质是:半支配点一定是 x 的祖先。因为不是祖先根本不可能全程绕dfn比x大的点来到x,一定要上跳一次。

 

然后我们说明一下,为什么把所有点的 (sdom(i),i) 连个边,然后保留一下树边,和原图具有相同的支配关系。

  • 添边是显然不改变的支配关系的,由引理就可以知道。
  • 考虑删边对 a 支配 b 的影响。显然仍然支配,因为边变少了,路径更少了,支配点可以被理解为S到这个点的割,也可以理解为 S到这个点的所有路径的交,割和交的角度都能很容易理解这一点。
  • 考虑删边对 a 不支配 b 的影响。考虑刚刚引入半支配点的流程,我们的那个调整,你会发现 a 不支配 b,就能按照那个流程调整,最后 a 被某个(sdom[x],x)跨过,x 是 b 的祖先,所以不支配关系也没有改变。

 

现在考虑怎么求 sdom ,求完之后套用 dag 的算法就行了。

 

我们倒叙考虑 dfn,这样更符合sdom的定义。

 

现在考虑计算 sdom[u] ,考察 sdom[u]->u 的最后一步, 只可能是由前向边,树边到达,或者横叉边,返祖边到达。一个 sdom[u] 来 u 的最后一步一定是4个之一。

  • 由前向边,树边过来:必然是是一步到位,这一类单独计算即可。
  • 由横叉边,返祖边过来:如果记x,表示从 x 过来,那么考察一个从 x 过来的路径,有什么性质,最好是可以通过以前的 sdom 递推。事实上,我们只需要考虑已经被扫描的 x 的祖先中, sdom的最小值,直接拿过来即可,下面我们来说明这一点。这个显然是一个合法路径,但是我们要证明这样计算不会漏掉某些路径。
    • 考虑一个可能的 y=sdom[x] 来 x 的路径,我们取这个路径上,除了头尾之外,dfn最小的点,记作 z 。
    • 考察 y->z ,那么根据定义, y 一定半支配 z,并且可以钦定 sdom[z]=y,因为这是贪心的,不影响后面的。
    • 考察 z->x ,因为 z 是dfn最小的,所以后续点 dfn 都大于 z,甚至跳不出 z 的子树,所以 z 一定是 x 的祖先,而且是被扫描过的。

既然如此,我们dfn倒着扫描的时候,用带权并查集,顺便把儿子们往父亲缩就行了,带权并查集维护的就是上面说的那个 sdom的最小值,要用的时候直接查询即可。由于我们用了 dag 的做法,需要倍增 LCA ,所以复杂度是 O(nlogn+(n+m)a(n)) 的。

(这其实是阉割版的 Lengauer-Tarjan,最后的dag暴力很丑陋)

 

 

 

 

后记:优化优化,再优化!

我们发现,刚刚的做法当 n,m 同阶的时候,dag那一部分居然反而是大头?我不能接受!Tarjan 当然也不能接受(

 

考虑优化。

实际上任何图已经可以被我们调整的很特殊的dag了,特殊到结构如此的清晰。

考虑 idom 能不能递推呢?

  • 一个点的 idom 一定在 sdom 的上面,如果 (sdom[x],x] 的 sdom 的 min 大于等于(实际上只可能等于)sdom[x] 那么显然 idom[x] = sdom[x] 。
  • 否则我们找到里面 sdom 最小的那个 y , 有 idom[x] = idom[y] ,其实也是很显然的,画个图就看出来了。

这样我们求 idom 就可以和 sdom 一起,总复杂度做到 O((n+m)a(n))

posted @ 2024-01-14 23:55  皮皮的橙子树  阅读(14)  评论(0)    收藏  举报