虛樹 Virtual Tree 學習筆記

2022-08-01 17:15:11 字數 1933 閱讀 3054

description

在一場戰爭中,戰場由n個島嶼和n-1個橋梁組成,保證每兩個島嶼間有且僅有一條路徑可達。現在,我軍已經偵查到敵軍的總部在編號為1的島嶼,而且他們已經沒有足夠多的能源維繫戰鬥,我軍勝利在望。已知在其他k個島嶼上有豐富能源,為了防止敵軍獲取能源,我軍的任務是炸毀一些橋梁,使得敵軍不能到達任何能源豐富的島嶼。由於不同橋梁的材質和結構不同,所以炸毀不同的橋梁有不同的代價,我軍希望在滿足目標的同時使得總代價最小。

偵查部門還發現,敵軍有一台神秘機器。即使我軍切斷所有能源之後,他們也可以用那台機器。機器產生的效果不僅僅會修復所有我軍炸毀的橋梁,而且會重新隨機資源分布(但可以保證的是,資源不會分布到1號島嶼上)。不過偵查部門還發現了這台機器只能夠使用m次,所以我們只需要把每次任務完成即可。

input

第一行乙個整數n,代表島嶼數量。

接下來n-1行,每行三個整數u,v,w,代表u號島嶼和v號島嶼由一條代價為c的橋梁直接相連,保證1<=u,v<=n且1<=c<=100000。

第n+1行,乙個整數m,代表敵方機器能使用的次數。

接下來m行,每行乙個整數ki,代表第i次後,有ki個島嶼資源豐富,接下來k個整數h1,h2,…hk,表示資源豐富島嶼的編號。

output

輸出有m行,分別代表每次任務的最小代價。

如果樹的點數少,可以用\(dp[u]\)表示子樹的所有關鍵點都不連通的最小代價,如果子節點\(v\)是關鍵點,則一定斷開\(uv\)這條邊,否則選擇是斷開\(uv\),還是使用子樹內的邊來阻斷,轉移即可,\(o(nq)\)。

不難發現其中很多點是無用的,對我們有用的點其實只有所有的關鍵點和他們之間的\(lca\),虛樹就是在不改變祖先與後代關係的情況下,保留了一些有用點,把一整顆樹的資訊進行壓縮,建出一棵小樹。

我們可以通過將關鍵點按\(dfs\)序排序,求出一些相鄰點的\(lca\),將他們加入虛樹中,同時保持祖先與後代的關係,這裡可以看出詢問\(n\)個關鍵點時,虛樹的節點數n小於等於\(2n-1\)

使用單調棧建虛樹,為了方便我們把\(1\)加入虛樹中。用單調棧來維護一條虛樹上的鏈,也就是乙個棧裡相鄰的兩個節點在虛樹上也是相鄰的,而且棧是從底部到棧首單調\(dfs\)序遞增的。

太懶了。。演算法細節還是看這裡

對於本題,建出虛樹後我們還要維護一些被壓縮路徑的最小值,可以倍增維護

#include typedef long long ll;

const int n = 250010;

using namespace std;

int n, q;

struct edge e[n << 1];

int cc, h[n];

void add(int u,int v,int w)

int dfn[n], id, fa[n][20], dep[n], mn[n][20];

void dfs(int u, int pre)

for(int i = h[u]; ~i; i = e[i].nxt)

}int lca(int u, int v)

int calmn(int u, int v)

bool cmp(int u, int v)

int a[n], mk[n], stc[n], top;

void build(int a, int m)

if(dfn[p] > dfn[stc[top-1]])

else

}h[a[i]] = -1, stc[++top] = a[i];}}

for(int w, i = 1; i < top; ++i)

}ll dp[n];

void dp(int u)

}int main()

dfs(1,0);

scanf("%d",&q);

while(q--)

}

日常學習 Virtual Tree 虛樹)

虛樹,顧名思義就是虛構的樹,它是一種用來解決樹上問題的演算法,主要思想是只將原樹上必要的點和它們的最近公共祖先取出來,構成一棵虛樹,並保留他們在樹上的相對關係。我們先來看一道題 給定一棵n個點的樹,每次詢問給定乙個大小為k的點集,你需要切掉一些邊,使得點集中的點均不與1號點聯通,而每條邊都有被切掉所...

Virtual Tree 學習筆記

像大部分虛樹介紹一樣,以一道 爛大街 的例題 sdoi2011 消耗戰 引入 給定一棵大小為 n 的樹,每條邊有邊權,m 組詢問,每次詢問給定 k 個關鍵點,要求切斷 1 與所有關鍵點的路徑,求最小代價。2 leq n leq 2.5 times 10 5 m geq 1 sum leq 5 tim...

虛樹學習小結

其實虛樹這東西 不知道說什麼好 簡單易學呃 虛樹主要處理一種詢問總點數不超過o n 且每次詢問的那些點,在預處理之後,所求的值,只和他們,以及他們兩兩的lca有關 這裡有個顯然的結論,即m個點兩兩的lca不超過m 1個,將這m個點按dfs序排序之後相鄰兩點的m 1個lca就是這m個點兩兩的lca 建...