動態平面圖邊雙連通性簡介
這個部分是冬令營交流里最後的一部分內容,也是最難的一部分,我覺得看懂這演算法對我來說還是有點困難所以先放點簡介吧……我還是太菜了 T T
本文尚在施工中,可能會更新
原文:J. Hershberger, M. Rauch, and S. Suri, Fully dynamic 2-edge-connectivity in planar graphs
Topology Tree
看完論文以後才對 Topology Tree 的用途有了一點進一步的認識。之前覺得這個複雜度根號,寫起來很麻煩還要處理度數才能用的數據結構到底是拿來幹什麼的。這個做法里發揮了很多 Topology Tree 的其他很多數據結構難以企及的地方,比如說:
我們可以在 的時間內把 Topology Tree 在某個節點處 展開,展開意味著用一些 Topology Tree 中(互不相交)的 cluster 來代表整棵樹(每個 cluster 看成一個點),且這些 cluster 中必須有一個只包含 的 cluster 。通過把 Topology Tree 在 展開我們可以得到一個點數 的新圖(cluster graph),只要我們能把 cluster graph 的信息(每個 cluster 內部, cluster 之間連邊)處理出來,那麼我們就可以在 cluster graph 上進行一般圖可以進行的操作(複雜的修改/詢問)了。
在之前看的 Topology Tree 里少提了一點,我們可以要求度數為 3 的 cluster 中只能包含一個點,複雜度不會改變。這就意味著每個 cluster 至多有兩個邊界節點 ,從而穿過這個 cluster 的路徑就唯一(即 ),因此我們可以維護這個路徑的相關信息。
基於這些想法,我們來介紹如何用 Topology Tree 維護平面圖邊雙連通性。我們的出發點和之前一致,通過維護生成樹中哪些樹邊被非樹邊覆蓋了來維護雙連通性。
以下用小寫字母代表樹上的節點,大寫字母代表 Topology Tree 中的 cluster 節點,如果我們用小寫字母(比如 等) 指代了 Topology Tree 中的某個節點,那就是樹上的節點在 Topology Tree 上對應的只包含了它(比如 )的 cluster 節點。
本文中 cluster 和塊是等價的。
Coverage Graph
如前所述,我們可以對於每個度數不超過 2 的 cluster 維護有關 的信息。我們考慮從所有塊內出發到塊外的邊,則這條邊會對 Topology Tree 中 到 的路徑上的所有塊產生影響。然而在一個塊內我們無法記錄所有 ,因為有的 可能並沒有在 cluster graph 上出現,這樣會破壞複雜度。但我們發現在 所在的塊我們並不關心 到底是誰,我們可以只用 來描述它所指向的目標(方向)。由於對於一個塊 而言 LCA 只有 種,考慮把 LCA 相同的邊分為一類。
由於我們並不知道 在離開 的時候到底是從 出去的還是從 出去的,我們還是不知道到底有哪些邊被覆蓋了。不過這些不重要,因為到了 cluster graph 里我們自然就知道這些了。我們考慮所有 LCA 相同的邊的 到 上的投影,令其中最左邊的點和最右邊的點分別為 ,我們可以發現如果最後從 出去被覆蓋的路徑就是 ,否則就是 。於是我們可以把 縮成一個點(無論如何都會被覆蓋)。縮點後的 稱作 coverage graph 。用鏈表維護所有縮起來的點,對於每個縮起來的點維護和它相關的所有種類的邊(縮點左側的邊和右側的邊分別用一個鏈表)。
Edge Bundles
我們用它們指向的 cluster 和這類邊的數量來表示一類邊,稱其為 Edge Bundle 。如之前所述目標設定為 ,稱為 LCA targeting 。為了處理修改和詢問我們需要把 LCA targeting 改成 precise targeting (即目標直接設定為 所在的 cluster ,由於是在修改和詢問時 cluster graph 中 所在的 cluster 是唯一確定的)。因此我們需要在兩種模式之間切換。
從 precise targeting 向 LCA targeting 切換是顯然的。對於反向的切換,由於 cluster graph 也是平面的,我們對這棵樹做一遍順時針的歐拉遍歷,所有非樹邊形成了一個其上形如 (((...))) 的括弧序列,因此我們可以掃一遍來確定哪些 edge bundle 是同一條邊。
Calculating the coverage graphs
為了計算塊 的 coverage graph 我們先計算兒子的再把它們的合併起來,有以下幾種情況:
- 只有一個兒子:什麼都不用做
- 有兩個度數為 3 和 1 的兒子: 的度數為 2 ,然而由於度數為 3 和度數為 1 都只有一個點所以直接把度數為 1 的 coverage graph 拿來就好了。
- 有兩個度數為 1 的兒子: 為根,兩個兒子的 coverage graph 里也只剩一個 edge bundle 了刪了就行了
- 有兩個度數為 2 和 1 的兒子:和下一種差不多但少了那種麻煩的情況,一起說
- 有兩個度數為 2 的兒子:令 和 是 的兒子,我們需要把連接 的 edge bundle 刪掉,至多有三個 edge bundle :在 左側右側可能有兩個,繞過整個生成樹一周可能會有一個。在左側右側的 edge bundle 可以通過鏈表的兩端來找到,另外一種如何找到之後會提到。在刪除 edge bundle 的時候我們把 上對應的部分縮起來。如果有相鄰的 edge bundle 有相同的目標也需要縮在一起(可以證明如果兩個 edge bundle 有相同的目標且不相鄰,那麼必然是繞過整個生成樹一周的邊)。
由於我們無法在所有點都存儲一份它自己的 coverage graph ,我們在合併過程中記錄合併的過程(稱為 recipe),在展開 Topology Tree 需要它兒子的 coverage graph 的時候再撤回即可。
Modification
由於詢問是在 cluster graph 上暴力詢問一遍就不多說了(由於 cluster graph 是平面的所以點邊都是 的),主要說修改。
幾種修改其實都大同小異,先說怎麼保證度數為 3 。我們把一個點表示成一個長度為其度數的環,每個環上的點度數為 2 剩下的一個度數用於連出邊。注意連的時候不要破壞原圖的平面性。
- 加入邊:展開 ,在 cluster graph 里加上這條邊
- 刪除非樹邊:展開 ,在 cluster graph 里刪去這條邊
- 刪除樹邊:展開 ,暴力找到一個連接 兩個連通塊的 edge bundle ,繼續 expand 下去直到我們確定這條用於替換的非樹邊,用這條非樹邊替換要刪的邊,然後把要刪的邊刪掉
進行這些步驟以後剩下的部分都是公共的:在已知修改的情況下更新 Topology Tree 。
首先我們確定修改後新樹的結構(但是暫時不對樹作出修改),把所有受到影響的 cluster 展開,然後我們切換到 precise targeting 並以此計算新的 LCA targeting ,接下來我們計算受影響的點的 recipe 。由於 LCA 改變,邊的 LCA targeting 受到影響,因此一些種類邊的 可能會發生改變。由於受影響的邊只有 條,涉及到需要重建的節點有 個,我們把它們也展開,從底向頂每次合併兩個塊,建出新樹。
關於合併在計算 coverage graph 的時候我們已經提到過了,但還有一種特殊情況要處理。我們維護每種深度的 edge bundle 有哪些。指向深度為合併後節點的深度的那個 edge bundle 必然就是我們所求的特殊邊(事實上 本來就該在 處被刪掉)。之後我們暴力把這條邊對應路徑上的點縮起來。均攤複雜度是 的。
推薦閱讀:
※你們用排序演算法排序八百萬個數的最快時間是多少?
※iPhone 5s 配備的 A7 處理器是 64 位,意味著什麼?
※反直覺:磁鐵可以消除硬碟的敏感數據么?
※帶你讀機器學習經典(二): An Introduction to Statistical Learning (Chapter 3.1 線性回歸)
※量子計算機的發展對傳統微電子行業是否有衝擊?
TAG:计算机科学 |