模擬賽要求圖上距離為 \(k\) 的節點對數,就學了一下圓方樹
眾所周知,樹有很多美妙的性質,但是有些題目非把樹上問題搬到圖上,這時我們就要上圓方樹了。
那麼圓方樹是什麼呢?(是圓形節點和方形節點構成的樹)
圓方樹(\(block \ forest\) 或 \(round-square \ tree\))1就是一種將圖變成樹的方法。本文將介紹圓方樹的構建,性質和一些應用。
圓方樹一開始是為「仙人掌」定製的。(每條邊在不超過乙個簡單環中的無向圖)
但是現在發現我們也可以在一般圖中使用它。
前置知識:點雙聯通分量。
割點的定義:在乙個圖中,如果把乙個節點 \(i\) 刪除後,原圖不再聯通,那麼我們稱這個點是割點。
點雙聯通分量的定義:當乙個圖中沒有割點,當前圖是點雙聯通分量。
我們用 \(tarjan\) 求出點雙聯通分量,在此不在累述。
而乙個圖的點雙連通分量則是乙個極大點雙連通子圖。
性質:與強連通分量等不同,乙個點可能屬於多個點雙,但是一條邊屬於恰好乙個點雙。
那麼在圓方樹中,每乙個原來的節點我們用圓形的點表示,每乙個點雙用方點表示。
給大家放幾個圖感受一下:
(來自 oi-wiki.org)
圓方樹的節點個數小於等於原來節點的兩倍,原因很簡單,因為原圖的點割點的個數最壞情況下也最多有 \(n\) 個,所以做題時注意陣列要開兩倍大小。
因為原圖中有多少個聯通分量就有多少個圓方樹,所以我們設原圖就是連通圖。
因為圓方樹的構建和點雙聯通分量有關,所以我們直接呼叫 \(tarjan\) 搞出割點就可以啦。
根據 \(tarjan\) 演算法:
每乙個low[i]
表示當前 \(i\) 節點最多一次返祖邊或向父親的樹邊 能訪問到的點的最小 dfs 序。
稍微構建乙個圖模擬一下就可以發現,對於每乙個點雙聯通分量,都是原圖中對應的乙個環,且每一條樹邊恰好被分在乙個點雙中,對於乙個點雙中最靠上的節點,滿足 \(dfn_i = low_i\) 的性質。
記錄乙個棧,儲存還未確定所屬點雙(可能有多個)的節點。(和 \(tarjan\) 一樣)
對於每乙個從棧彈出的節點,我們讓它和新建的節點相連線。記得最後要和 \(u\) 相連。
如圖所示:(無加粗的是新加入的方形節點)
// addline 為圓方樹的邊
// head2, to2.... 為原圖的邊
inline void tarjan(int now)
addline(cnt, sta[top]);
addline(sta[top], cnt);
top--;
addline(now, cnt);
addline(cnt, now);
}} else
low[now] = std::min(low[now], dfn[t]);
}}
p4630 [apio2018] duathlon 鐵人兩項
cf487e tourists
學習筆記 圓方樹
圓方樹 元芳你怎麼看 圓方樹推薦 圓方樹是什麼?tarjan家族中,最不好處理的是點雙 因為乙個割點可能屬於很多的dcc。為了把圖縮成一棵樹,我們不得不做出這樣的處理 摘自 這個樹不但醜。而且,對於乙個點雙內部的資訊,我們把它縮成了乙個點,內部的與非割點有關的路徑我們一無所知。所以這個玩意只能用來維...
圓方樹學習筆記
聽說g2的選手都會圓方樹了,所以我來學習一波。這個階段的學習我也僅僅只是知道了圓方樹是什麼,比較簡單的題目怎麼寫,但是對於一些思維難度較高,實現能力要求較高的題目,我還不是很會.希望未來能越來越好 點雙連通分量,仙人掌的定義。點分為圓點和方點的樹.把仙人掌上的點保留,然後如果存在乙個點雙就新建乙個方...
圓方樹學習筆記
寫這個東西只是記錄一下我學過圓方樹 text 圓方樹是一種將圖變成樹的方法。首先,把原圖中的所有點都看成圓點,我們需要求出圖中所有的點雙連通分量,可以使用 tarjan 演算法。然後,在每乙個點雙連通分量中間建立乙個方點,將此點雙連通分量中的所有點向這個方點連邊。這樣就可以把圖轉成樹,利用一些樹上的...