虛樹入門筆記

2022-02-07 12:29:31 字數 1317 閱讀 4995

前置芝士: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 序從小到大排好序 ...