给定一颗树,树中包含 n� 个结点(编号 1∼n1∼�)和 n−1�−1 条无向边。
请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。
重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。
输入格式
第一行包含整数 n�,表示树的结点数。
接下来 n−1�−1 行,每行包含两个整数 a� 和 b�,表示点 a� 和点 b� 之间存在一条边。
输出格式
输出一个整数 m�,表示将重心删除后,剩余各个连通块中点数的最大值。
数据范围
1≤n≤105

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <set>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const ll maxx = 1e9;
int n, m, T;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1.0);
int dx[4] = { 0 , 1 , -1 , 0 }, dy[4] = { 1 , 0 , 0 , -1 };
int h[N], e[N * 2], ne[N * 2];//h邻接表储存树, 有n个节点//e储存元素//ne储存列表的next值
int idx;//单链表指针
int ans = N;//表示重心的所有的子树中,最大的子树的节点数
bool st[N];//记录节点是否被访问过,被访问过就标记为true
void add(int a, int b)//邻接表//a对应单链表中插入b,a作为根
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
//返回以u为根的子树中的节点的个数,包括u节点
int dfs(int u)
{
int res = 0;
st[u] = true;//标记访问过的u节点
int sum = 1;//储存以u为根的树的节点数,包括u,
//访问u的每个子节点
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j])
{
int s = dfs(j);//u节点的单棵子树点数
res = max(res, s);//记录最大联通子图的节点数
sum += s;
}
}
res = max(res, n - sum);//选择u节点为重心 , 最大的连通子图节点数
ans = min(res, ans);//遍历过的假设重心中, 最小的最大联通子图的节点数
return sum;
}
void solve()
{
memset(h, -1, sizeof(h));//初始化节点,-1表示尾结点
cin >> n;
//树不存在环,对于有n个节点的树,必定是n - 1条边
for (int i = 0; i < n - 1; i++)
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a);//无向图
}
dfs(1);//任选一个节点就行//因为是无向图
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
//cin >> T;
//while (T--)
//{
solve();
//}
return 0;
}