LG5180[模板]支配树【Lengauer-Tarjan算法】
转载自https://www.luogu.org/problemnew/solution/P5180
来一个$Tarjan$老爷子的$Lengauer-Tarjan$算法吧
最优是$O(nα(n))$ 但是会被卡成$O(nlogn)$
(这里默认nm数量级同阶)
1.定义
对于一棵可以存在环的有向图
给定一个起点$r$ 对于一个终点$x$ 如果$r$到达$x$的所有路径都会经过一个点$y$
那么我们就称之为$y$支配$x$
我们令支配$x$的点集为$S=p_1,p_2,p_3,......,p_k$
那么从起点$r$到达$x$的任意一条路径排列为$r......p_1......p_2......p_k...x$
支配树可以对于每一个点$x(x!=r)$求出$p_k$ 也就是点集$S$当中距离$x$最近的支配点
这个点我们称之为$idom[x]$
如果每一个点连出指向$idom[x]$ 那么就构成了一颗内向树 我们称之为支配树
2.算法
1.首先我们需要一颗$DFS$树
也就是对这个算法进行$dfs$遍历 求出其$dfs$序
2.半必经点
从$y$出发到$x$ 存在这样一条路径 路径上的点(不包括$x$以及$y$)的$dfn$均大于$dfn[x]$ 我们称$y$是$x$的半必经点
$sdom[x]$表示$x$的半必经点中$dfn$最小的点
为什么要求这个点呢 ? ? ? 我们删掉原图中的非树边 然后连接$(sdom[x],x)$ 不改变原图中的支配点关系
这样的话 我们就把原图变为了一个$DAG$ 就可以使用$DAG$的做法了 但是还有更优的方法
求半支配点
对于一个点$x$ 找出所有的边$(y,x)$中对应的$y$
若$dfn[y] < dfn[x]$且$dfn[y]$比当前找到的$sdom[x]$的$dfn$小 那么就用$sdom[x]=y$
若$dfn[y]>dfn[x]$ 找到树上$y$的一个祖先$z$ 并且$dfn[z]>dfn[x]$ 比较$dfn[sdom[z]]$同$dfn[sdom[x]]$ 决定是否用前者更新后者
从半支配点到支配点
对于$x$ 我们要的是$idom[x]$
寻找方法如下
我们令$P$是从$sdom[x]$到$x$的树上路径点集(不包括$sdom[x]$) 而且$z$是$P$中$dfn[sdom[z]]$最小的点
如果$sdom[z]=sdom[x]$ 那么$idom[x]=sdom[x]$ 否则就是$idom[x]=idom[z]$
算法流程
我们用带权并查集来实现
首先按照$dfs$序从大到小处理 每一次处理完毕一个点之后 将这个点同其在$dfs$树上的父亲在并查集连边
而并查集的权 就是并查集这个点到根节点的路径上的所有点 最小的$dfn[sdom[x]]$对应的$x$
找$sdom[]$直接找即可 找$idom$可以使用$sdom[x]$处理