Live2D

支配树(灭绝树) 学习笔记

前言

在飞机上的时候理解了一下这个算法,这里写一下吧。本来以前一直以为是个H2O算法(其实也是),结果发现一些证明还是很有意思的。

前置定义

对于一个给定图,我们有如下定义:

  • 支配点

我们称uv的支配点当且仅当在原图中删去u之后从根节点出发无法抵达v

  • 半支配点

我们称uv的半支配点当且仅当u存在一条到v的路径使得该路径除去u,v所有节点的dfn都大于dfn[v],且u在满足条件的点集中dfn最小。

为了方便,我们称点u的半支配点为sdom[u],支配点为idom[u]

支配树思想

这个算法主要是解决支配之类的问题。例如一个点支配多少个点,一个点被多少个点支配之类的。

对于这个问题我们可以建起一棵树,满足点u支配的点都在u的子树内。

于是问题就是如何建起一棵支配树,据说这个还叫灭绝树(奇怪的名字增加了!!!)

很显然,对于一棵树,该树的支配树就是它本身。

  • DAG

很显然,我们可以直接把点u连在lca(v1,v2,...)的下面,其中存在边v1,v2,...u

时间复杂度Θ(nlogn)

例题: [ZJOI2012]灾难

  • 任意图

对此,我们Tarjan老爷子和Lengauer提出了一种名为Lengauer-Tarjan的算法,可以在Θ(nlogn)的时间复杂度内建好树,当然,更确切的来说是Θ(nα(n))

我们发现似乎我们直接求支配点不是很好求,我们考虑如何求出半支配点。

我们发现对于当前节点u,如果有边vu,且dfn[u]<dfn[v],那么在不考虑dfn最小的情况下,一定sdom[v]u的半支配点。

证明直接感性一下,发现显然,直接根据定义就可以知道正确性。

而且半支配点还有一个性质,就是一个点的半支配点的dfn一定不会比该点大,这个下面的性感证明会用到,但是我似乎并没有写出来,读者明白就好。

然后这里就有一个Θ(nlogn)的方法诞生了。我们发现如果删掉原图中非dfs树的边,再对于u,连上sdom[u]u,不会改变原图的支配关系。

正确性这里感性证明一下,对于u,v,如果在原图中u并不支配v,那么,如果在dfs树中u不是v的祖先,那显然满足,否则的话,我们可以从sdom[v]走到v。如果原图中u支配v的话,很显然,在dfs树中uv的祖先,因为无论怎么走都得先经过u。那么显然u还支配v

于是,我们就把这个图变成了一个DAG,就可以用上面的方法Θ(nlogn)做出来了。

但是,这并不满足我们对代码复杂度的渴望。一个小小的思想在我们脑海中划过:我们是否可以用sdom求出idom?答案是肯定的。为了方便,我们假设我们已经把图变成一个DAG了。

我们分两种情况考虑:

我们设zsdom[x]x路径上dfn[sdom[z]]最小的点

  1. 如果sdom[z]=sdom[x]

idom[x]=sdom[x]

这个应该很显然吧。。。性感理解的话就是因为不可能有其他点通过sdom边走到sdom[x]x的路径上,因为这条路径上dfn[sdom[z]]最小值也不过sdom[x]

  1. 否则

idom[x]=idom[z]

我们采用反证法来感性证明一下:

我们假设删去idom[z]之后仍可达idom[x],那么说明idom[z]的某个祖先可以通过sdom边走到idom[z]x这条路径上的某个点,但是我们发现idom[z]必定是sdom[z]的后代,而sdom[z]z这条路径上dfn[sdom[z]]最小也不过z,所以矛盾,证毕。

于是,我们可以用并查集维护sdom[x]xdfn[sdom[  ]]的最小值,我们就在Θ(nα(n))的时间复杂度内解决了建树的问题。

对了,还有最后的一个问题没有解决,可能细心的读者已经发现了(似乎也木有什么读者),我们并没有说明一个点支配的点都在支配树的子树内。其实很好说明,我们发现我们全都是用的dfn最小的点,这就满足充分性。

The 1st

P5180 【模板】支配树

这个题确实就是板题,就是建出支配树后求出子树大小。

代码戳这里打开

The 2ed

题目大意#

给出一个n个点m条边的带权无向图,给定起点s,求出一个点使得删去该点之后最短路变化的点数最多。

思路#

这道题其实还是比较妙的。

我们不难想到先对原图建出一个最短路径图,于是一个点删去产生的贡献就是该图中支配的点数。这个仔细想一下就会明白为什么。

我们发现这个最短路径图一定是个DAG,因为里面如果有环的话就不是最短路径图了,于是我们就可以直接用LCAΘ(nlogn)解决。

于是我们就在Θ(nlogn+m)的时间复杂度内解决了这个问题。

代码戳这里打开

posted @   Dark_Romance  阅读(407)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
CONTENTS