支配树
為了方便本文的敘述,做出如下可能不嚴謹?shù)亩x:
對于一棵樹,我們可以用\([x,y]\)簡潔的表示從\(x\)到\(y\)的路徑上的所有點組成的集合,假如我們希望這個集合不包含\(x\)或\(y\),只要將閉區(qū)間改為開區(qū)間即可。如\([x,y)\)表示從\(x\)到\(y\)的路徑上的所有點(不包含\(y\))組成的集合。
我們從一道簡單的板子題(在讀完這篇文章以后就是了)開始:
給定一個\(n\)個點,\(m\)條邊的有向圖\(G\),以及一個出發(fā)點\(r\)。詢問\(q\)次,每次給定點\(x\),\(y\),保證從\(r\)出發(fā)可以到達\(x\)。問從\(r\)出發(fā)到達\(x\)的所有路徑是否都需要經(jīng)過\(y\)。
\(n,m,q\leq 10^5\)。
為了解決這個問題,我們定義有向圖上的支配關系:對于一個固定的出發(fā)點\(r\),如果從\(r\)出發(fā)到達\(x\)的所有路徑都需要經(jīng)過\(y\),則稱\(y\)是\(x\)的支配點,即\(y\)支配\(x\)。特別的,我們認為\(x\)不是\(x\)的支配點。
我們來研究一下支配關系有哪些性質:
首先,我們將以\(r\)為根的\(dfs\)樹建立出來。容易發(fā)現(xiàn),對于任意一個點\(x\),它的所有支配點只可能是它的祖先——顯然,對于不是它的祖先的任意一個點\(y\),我們從\(r\)通過樹邊到達\(x\)就不需要經(jīng)過\(y\)。
接著我們假設\(y\)是\(x\)的支配點中深度最大的(即距離\(x\)最近的),那么還可以發(fā)現(xiàn):對于\(z\neq y\),\(z\)是\(x\)的支配點當且僅當\(z\)是\(y\)的支配點。
證明如下:
首先證明充分性。如果\(y\)支配\(x\),\(z\)支配\(y\),那么假設\(z\)不支配\(x\),即存在一條路徑不經(jīng)過\(z\)。那么顯然由于這條路徑必定經(jīng)過\(y\),于是我們就找到了一條不經(jīng)過\(z\)到達\(y\)的路徑,這與前提條件矛盾,于是假設不成立,充分性得證。
再證明必要性。如果\(y\)支配\(x\),\(z\)不支配\(y\),顯然可以找到一條路徑不經(jīng)過\(z\)而到達\(y\)。此時由于\(y\)是深度最大的\(x\)的支配點,因此沿著樹邊一直走到\(x\),必定不會經(jīng)過\(z\),于是\(z\)就不可能是\(x\)的支配點。
于是我們就可以知道,對于任意一個點\(x\),我們只要找到它深度最大的支配點\(y\),其余的支配點就都是\(y\)的支配點。不難發(fā)現(xiàn),這樣的支配關系形成了一個類似樹的結構,將之前所說的\(y\)當作\(x\)的父親的話,那么\(x\)的所有支配點就是這棵樹上它的祖先。我們將這棵樹叫做支配樹,將這樣的\(y\)記為\(idom(x)\)。
那么問題來了,如何求出\(idom(x)\)呢?
為了解決這個問題,我們先定義一個叫做半支配的東西:
對于任意一個點\(x\),從\(y\)出發(fā),只經(jīng)過不是\(x\)的祖先的點就可以到達\(x\)(不包含\(x\),\(y\)),則稱\(y\)是\(x\)的半支配點,即\(y\)半支配\(x\)。
首先,我們可以發(fā)現(xiàn)\(x\)的深度最小的半支配點一定是\(x\)的祖先。因為假設\(x\)的深度最小的半支配點\(y\)不是\(x\)的祖先,那么顯然我們可以沿著樹邊往回走,一直走到某個\(x\)的祖先\(z\)上。這其間肯定不會經(jīng)過除\(z\)以外的\(x\)的祖先點,于是\(z\)的深度比\(y\)小,且也是\(x\)的半支配點,于是假設不成立,得證。
接著,如果\(y\)是\(x\)的深度最小的半支配點,那么樹上路徑\((x,y)\)中的點就顯然不是\(x\)的支配點——因為從\(y\)出發(fā)存在一條路不經(jīng)過它們而到達\(x\)。我們將這樣的\(y\)記為\(sdom(x)\)。
我們來考慮如果求得了半支配點,那么如何求支配點??紤]對于一個點\(x\),樹上路徑\((x,sdom(x))\)中的點一定不是\(x\)的支配點。并且對于任意一個\(x\)的祖先\(y\),樹上路徑\((y,sdom(y))\)中的點也一定不是\(x\)的支配點。反之,如果某個\(x\)的祖先\(z\)不被\((x,sdom(x))\)和任何一個\((y,sdom(y))\)包含,那么\(z\)一定是\(x\)的支配點——否則一定會存在一條不經(jīng)過\(z\)的路徑\(S\)到達\(x\),\(S\)中一定存在兩個\(x\)的祖先\(a,b\)使得樹上路徑\((a,b)\)經(jīng)過\(z\)而\(a,b\)之間不經(jīng)過其它\(x\)的祖先,于是\(z\)一定會被某個區(qū)間包含。
于是\(idom(x)\)就是不被如上所述的這些區(qū)間包含的\(x\)的祖先中深度最大的??紤]遞歸解決這個問題,如果\(y\)是\([x,sdom(x))\)中\(sdom(y)\)的深度最小的,那么如果\(sdom(y)\)就是\(sdom(x)\),顯然\(sdom(x)\)不會被任何區(qū)間包含了,那么\(idom(x)\)就是\(sdom(x)\)。否則我們就去掉區(qū)間\((x,sdom(x))\)并求對于\(y\)來說這個問題的答案即可——而這就是\(idom(y)\),已經(jīng)求好了。
好,現(xiàn)在解決最后一個問題,如何求出\(sdom(x)\)。分兩種情況討論:
\(1)\)最后一條邊為前向邊或樹邊。顯然另一端就是\(x\)的祖先,路徑必須結束。這種情況可以直接得到半支配點。
\(2)\)最后一條邊為橫插邊或后向邊,設走到的點為\(y\),而\(x\),\(y\)在\(dfs\)樹上的\(lca\)為\(z\)。由于\(lca\)為\(z\),因此樹上路徑\([x,z)\)中的點一定無法到達\([y,z)\)中的點,于是對于\([y,z)\)的\(sdom\)來說,不會有經(jīng)過\([x,z)\)中的點的路徑,那么顯然樹上路徑\([y,z)\)中的點對于\(x\)來說都是合法的。于是用樹上路徑\([y,z)\)中的點的\(sdom\)來更新\(sdom(x)\)即可??梢园l(fā)現(xiàn)沿著時間戳反向求\(sdom\)的話,我們求\(sdom\)的順序就不會沖突。
于是我們就解決了文章開頭提到的那個問題。至于具體的實現(xiàn),我們在反向求\(sdom\)的過程中可以用帶權并查集維護一段樹上路徑的\(sdom\)最小值,在求完一個點的\(sdom\)以后將它的兒子與它合并即可。這樣每次查詢時并查集維護的恰好就是我們需要的那一條鏈。至于求\(idom\)的過程,我們需要知道\([x,sdom(x))\)的信息,于是將請求接入\(sdom(x)\)的鏈表中。每一次求完\(x\)的\(sdom\)后,我們掃描其父親的請求鏈表,對于鏈表中每一個\(y\),可以發(fā)現(xiàn)帶權并查集此時維護的就是我們要查詢的區(qū)間\([y,sdom(y))\),直接從帶權并查集上得知\(sdom\)最小的為哪一個并存下來并清空鏈表,在最后求\(idom\)時直接用即可。
時間復雜度\(O((n+m)\log n)\)。
有向圖上還有類似的支配邊的關系,容易發(fā)現(xiàn)只有樹邊能成為支配邊。且如果一條邊\(y\to x\)為\(x\)的支配邊,需要\(y\)為\(x\)的支配點,且對于所有有非樹邊指向\(x\)的點\(z\),都有\(x\)支配\(z\)。
有向圖上還有割點、橋、點雙、邊雙的定義。不過還是下次填坑吧...
參考鏈接:https://zhuanlan.zhihu.com/p/30432617
轉載于:https://www.cnblogs.com/Mr-Spade/p/10106905.html
總結
- 上一篇: html5 新增input类型,html
- 下一篇: XMind思维导图教程:如何做思维导图?