1. 程式人生 > >LG5180[模板]支配樹【Lengauer-Tarjan算法】

LG5180[模板]支配樹【Lengauer-Tarjan算法】

不改變 直接 算法 進行 org http 尋找 www pro

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]$處理

LG5180[模板]支配樹【Lengauer-Tarjan算法】