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

 

posted @ 2021-10-20 17:03  Modest-Hamilton  阅读(141)  评论(0)    收藏  举报