dsu on tree 啟發式合併演算法
阿新 • • 發佈:2019-01-25
我們先引入這樣一個問題:
有一棵樹,樹上有很多結點,每個結點有一個顏色c
,我們現在想知道樹上每個結點的子樹**(subtree)**,有多少個結點出現顏色c
。子樹的定義:該結點和其所有的孩子構成的樹。
如上圖:
- 結點1子樹:3個結點出現黃色,2個結點出現紅色
- 結點2子樹:2個結點出現黃色,1個結點出現紅色
- 結點3子樹:1個結點出現紅色
- 結點4子樹:1個結點出現黃色
- 結點5子樹:1個結點出現紅色
我們現在丟擲一個問題;
樹上每個結點的子樹**(subtree)**,有多少個結點出現顏色黃色
暴力做法
不難想到,我們可以dfs遍歷整個樹,然後對結點再一次dfs(subtree),計算多少個點出現黃色,程式碼如下:
int cnt[maxn];
void add(int v, int p, int x){//v結點,p父節點
cnt[ col[v] ] += x;
for(auto u: g[v])
if(u != p)
add(u, v, x)
}
void dfs(int v, int p){
add(v, p, 1);
//現在cnt陣列記錄
add(v, p, -1);
for(auto u : g[v])
if(u != p)
dfs(u, v);
}