树的重心
给定一颗树,树中包含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
题解:
/*
File_created: Monday,February 1th 2021, 22:18
Author: onmyown
Problem: 树的重心
*/
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 using namespace std; 5 6 const int N = 1e5 + 10; 7 8 //链表存储每个点的边 9 10 int h[N]; // 存储每个点的头结点 11 int e[2*N]; //存储元素, 无向图,双向边,*2 12 int ne[2*N]; //存储链表的next值 13 int idx; 14 15 int n; 16 int ans = N; // 记录子树的最小值 17 18 bool st[N]; //记录该点是否已经被查找过了 19 20 int add(int a, int b) 21 { 22 e[idx] = b; 23 ne[idx] = h[a]; 24 h[a] = idx ++; 25 } 26 27 28 int dfs(int u) 29 { 30 int siz = 0; //存放连通块中点的 个数的最大值 31 st[u] = true; 32 33 int sum = 0; //sum记录子树的个数 34 35 for(int i = h[u]; i != -1; i=ne[i]) 36 { 37 int j = e[i]; 38 39 if(!st[j]) 40 { 41 int s = dfs(j); 42 siz = max(siz, s); 43 sum += s; 44 } 45 } 46 siz = max( siz, n- sum -1); // n-m 即总结点—根的子树结点数,=剩余联通结点数 47 ans = min(ans, siz); 48 return sum +1; //因为sum 初始化0, 当前这个点也算连通块中的一个 49 50 } 51 52 int main() 53 { 54 memset(h, -1, sizeof h); //初始化 -1 表示空链表 55 scanf("%d",&n); 56 57 for(int i =0; i < n-1; i++) //n-1 是n个点,n-1条边 58 { 59 int a, b; 60 scanf("%d%d",&a,&b); 61 add(a,b); 62 add(b,a); //无向图, 双向边 63 } 64 65 dfs(1); 66 67 cout << ans <<endl; 68 return 0; 69 }

浙公网安备 33010602011771号