1. 程式人生 > 其它 >【DFS】樹的重心

【DFS】樹的重心

題目描述

給定一顆樹,樹中包含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 }