树的重心

给定一颗树,树中包含n个结点(编号1~n)和n-1条无向边。

请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。

重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。

输入格式

第一行包含整数n,表示树的结点数。

接下来n-1行,每行包含两个整数a和b,表示点a和点b之间存在一条边。

输出格式

输出一个整数m,表示将重心删除后,剩余各个连通块中点数的最大值。

数据范围

1n105

 

输入样例

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 }

 

posted @ 2021-02-01 22:21  Leo-aiolia-bao  阅读(57)  评论(0)    收藏  举报