【DFS】樹的重心
阿新 • • 發佈:2021-10-20
【題目描述】
給定一顆樹,樹中包含n個結點(編號1∼n)和n−1條無向邊。
請你找到樹的重心,並輸出將重心刪除後,剩餘各個連通塊中點數的最大值。
重心定義:重心是指樹中的一個結點,如果將這個點刪除後,剩餘各個連通塊中點數的最大值最小,那麼這個節點被稱為樹的重心。
【輸入格式】
第一行包含整數n,表示樹的結點數。
接下來n−1行,每行包含兩個整數a和b,表示點a和點b之間存在一條邊。
【輸出格式】
輸出一個整數m,表示將重心刪除後,剩餘各個連通塊中點數的最大值。
【資料範圍】
1≤n≤105
【輸入樣例】
9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6
【輸出樣例】
4
思路:計算出樹中所有結點被刪去後剩下的連通塊的節點數,在其中找出連通塊最大值的最小值來。
統計每個結點的連通塊最大值,可以首先DFS計算結點A的每個子樹結點個數,對於A的父結點連通塊的節點個數,可以使用結點總數num減去結點A以及所有結點A的子樹結點個數。
1 #include <iostream> 2 #include <string.h> 3 using namespace std; 4 5 const int N = 100009; 6 int h[N],e[2*N],ne[2*N],idx,st[N]; 7 int ans = 1e9; 8 int n; 9 void add(int a,int b) 10 { 11 e[idx] = b;12 ne[idx] = h[a]; 13 h[a] = idx++; 14 } 15 16 int dfs(int u) 17 { 18 int sum = 1,res = 0; 19 for(int i = h[u];i != -1;i = ne[i]) 20 { 21 int j = e[i]; 22 if(!st[j]) 23 { 24 st[j] = 1; 25 int s = dfs(j); 26 res = max(res,s);27 sum += s; 28 } 29 } 30 res = max(res,n - sum); 31 ans = min(ans,res); 32 return sum; 33 } 34 35 int main() 36 { 37 memset(h,-1,sizeof h); 38 cin >> n; 39 for(int i = 0;i < n - 1;++i) 40 { 41 int a,b; 42 cin >> a >> b; 43 add(a,b); 44 add(b,a); 45 } 46 dfs(1); 47 cout << ans << endl; 48 return 0; 49 }