前置芝士:lca,dfs序
參考內容 「**虛樹」, 洛谷**「**虛樹」(實際上是同一篇/lh)
對於一棵給定的 \(n\) 個節點的樹 \(t\),構造新樹 \(t'\) 使其包含指定點集及它們的 lca, 且節點數最小。這樣的 \(t'\) 被稱為虛樹。
虛樹可以解決樹上對於指定點集 \(s\) 的詢問,時間複雜度可以實現 \(\mathrm\),其中 f 為樹上解決該問題所需複雜度, 前者則為建樹複雜度。
進行 lca 與 dfs 序預處理,對於詢問的點集按照 dfs 序排序,按照這樣的順序構造。
維護乙個棧,儲存虛樹中從根到當前節點的路徑。
我們考慮對於某乙個將要加入虛樹的新點,設其為 \(u\), 此時棧頂為 \(st_\),求出它們的 lca。
因為根據 dfs 序排過序,新點 u 不可能是 lca, 於是進行分情況討論:
執行到最後將棧中點全部彈出並連邊,完成虛樹構建。
建樹** \(\mathbf\)
inline void inc(int x, int y)
inline void tend(int u)
inline void build(vectors)
瓶頸在於點集排序和樹上 lca ,加上了個棧,每個元素進棧一次出棧一次,具體為\(\mathrm\),常數不計。
瓶頸複雜度 \(\mathrm\)。
注意每次回答完詢問後的清空虛樹操作一定要注意時間複雜度,memset 大多致死。
當然也要注意空間複雜度,如果開了靜態陣列,就要算算是否會爆空間,當然 vector 是乙個好選擇。雖說很多虛樹的題空間都會給夠。
struct virtualtree }
inline void dfs2(int u, int k) }
inline void set(int _)
inline int lca(int x, int y)
inline void clear()
inline void inc(int x, int y)
inline void chain(void)
inline void tend(int u)
inline void build(vectors)
} v;
入門例題首選 cf613d kingdom and its cities.
再有 [sdoi2011]消耗戰
虛樹學習筆記
將關鍵點按dfs序排序後,所有關鍵點與相鄰關鍵點的lca合起來構成虛樹 通常還要加上整棵樹的根 虛樹至多有2k2k 個點。體現在實現中就是每次都pop若干點,並有機會push2個點。stk中存的是從根到當前點的遞迴棧中目前選入虛樹的點。stk中的點之間都未連邊 因為事實上關係還未確定 pop掉乙個點...
虛樹 學習筆記
水平不夠,學習來湊 又開了個天大的新坑 sdoi 2011 消耗戰 題目大意就是講 給出一棵樹,有邊權,然後給出k個查詢點,問從1號店不能到任何乙個查詢點的代價是多少.先考慮一下樹形動歸.dp i 表示從1不能到以i為根的子樹中的所有查詢點的最小代價 考慮維護乙個量,mins i 表示從1到i路徑最...
虛樹學習筆記
虛樹常常被使用在樹形 dp 中。有些時候,我們需要計算的節點僅僅是一棵樹中的某幾個節點 這個時候如果對整棵樹都進行一次計算開銷太大了 所以我們需要把這些節點從原樹中抽象出來 按照它們在原樹中的關係重新建一棵樹,這樣的樹就是虛樹 在構建之前,我們需要把所有需要加入的節點按照 dfn 序從小到大排好序 ...