【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 }

浙公网安备 33010602011771号