题目描述 :
给定一颗树,书中包含 n 个结点(编号 1∼n )和 n−1 条无向边。
请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。
重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。
输入输出格式 :
输入
第一行包含整数 n,表示树的结点数。
接下来 n−1 行,每行包含两个整数 a 和 b,表示点 a 和点 b 之间存在一条边。
输出
输出一个整数 m,表示将重心删除后,剩余各个连通块中点数的最大值。
输入输出样例 :
输入
9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6
输出
4
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int dir[4][2] = { 1, 0, -1, 0, 0, 1, 0, -1 };
//using lll = __int128;template <class T> istream& read(T& x, istream& cin = std::cin){T num = 0;bool f = 0;char ch = 0;while (!isdigit(ch)) {f |= ch == '-';if (!cin.get(ch)) return cin;}while (isdigit(ch)){num = (num << 3) + (num << 1) + (ch ^ 48);if (!cin.get(ch)) break;}x = f ? -num : num;return cin;}template <class T> ostream& write(T x, ostream& cout = std::cout) {if (x < 0) cout.put('-'), x = -x;if (x > 9) write(x / 10);cout.put(x % 10 + '0');return cout;}ostream& operator<<(ostream& cout, lll x) {write(x);return cout;}istream& operator>>(istream& cin, lll &x) {return read(x);}bool check(int i, int j);
bool check(int i, int j);
const int N = 1e5 + 10, mod = 1e9 + 7, INF = 0x3f3f3f3f;
int n, m, h[N], ne[N], e[N], idx, w[N], ans = INF;
vector<int> g[N];
void init() {
memset(h, -1, sizeof h);
cin >> n;
for (int i = 0; i < n - 1; i ++) {
int x, y;
cin >> x >> y;
g[x].emplace_back(y);
g[y].emplace_back(x);
}
// cout << "初始化完成\n";
return;
}
int dfs(int u, int pre) {
int res = 0, sum = 1; //u为重心时最大连通块的节点数, 以u为根节点的子树的总节点数
for (auto &rnx : g[u]) {
if (rnx == pre) continue;
int d = dfs(rnx, u);
sum += d;
res = max(res, d);
}
res = max(res, n - sum); //假如u是重心,则去掉u后u的子树最大连通块节点为res,u的父节点所在的树的最大连通块为 n - sum
ans = min(res, ans);
return sum;
}
void solve() {
dfs(1, -1);
cout << ans;
return;
}
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
cout << setprecision(6) << fixed;//保留6位小数从小数点后计数
int TT = 1;
//cin >> TT;
for (int ii = 0; ii < TT; init(), solve(), ii++, cout << "\n") {}
return 0;
}
#include<bits/stdc++.h>
#define mxt INT_MAX
#define mnt INT_MIN
#define LL long long
#define vt(x) vector<x>
#define vp(x,y) vector<pair<x,y>>
#define vt_t(x) vector<x>::iterator
#define ed end()
#define bg begin()
#define pb push_back
#define all(x) x.bg,x.ed
#define si(x) ((int)x.size())
#define NZ 1000000007
using namespace std;
const int N = 1e5 + 10;
int n, m;
int h[N], e[N], idx, ne[N], vis[N] = { 0 };
int ans = N;
void add(int i, int j) {
ne[idx] = h[i];
e[idx] = j;
h[i] = idx++;
return;
}
//以u位根的子树的节点点数
int dfs(int u) {
vis[u] = 1;
int sum = 1, res = 0;
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if (!vis[j]) {
int s = dfs(j);
res = max(res, s);
sum += s;
}
}
res = max(res, n - sum);
ans = min(ans, res);
return sum;
}
void init() {
cin >> n;
memset(h, -1, sizeof(h));
for (int i = 0; i < n - 1; i++) {
int a, b;
cin >> a >> b;
add(a, b);
add(b, a);
}
// cout<<"初始化完成\n";
return;
}
void solve() {
dfs(1);
cout << ans << endl;
return;
}
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
cout << setprecision(12);//保留6位
cout << fixed;//从小数点后计数
init();
solve();
return 0;
}