总结,在无向树中,根节点可以是任何一个。
dfs过程中一定是一个树的结构,因此在dfs中就确定了一个搜索树。
dfs(1)表示是默认1为根节点,从1开始搜索。
在割去了第i
个点后剩下的连通块是
该点的儿子构成的联通块
根节点-它的儿子们联通块-该点
因为在邻接表中,即有该点到其父亲的点,又有该点到其儿子的点,所以需要记录一个点的父亲是谁。
于是有了fa[maxn]
用于记录该点的父节点。
最后由于1是根节点,没有父亲,所以就拿出来特殊处理。
#define judge
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const int ninf = 0xcfcfcfcf;
const double pi = acos(-1.0);
static int faster_iostream = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
return 0;
}();
int n;
const int maxn = 1e5 + 10;
int h[maxn], e[maxn * 2]; // h链表头 e值 ne指针
int ne[maxn * 2], idx;
bool used[maxn];
int cnt[maxn];
int fa[maxn];
void add(int a, int b) {
//在a点到b插入一个边
//在a表中插入一个点
e[idx] = b;
ne[idx] = h[a];
h[a] = idx;
idx++;
}
int dfs(int u) {
if (used[u] == true) return cnt[u];
int res = 1;
used[u] = true;
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if (!used[j]) {
fa[j] = u;
res += dfs(j);
}
}
return cnt[u] = res;
}
void init() {
idx = 0;
memset(h, -1, sizeof h);
}
int res = inf;
int main() {
#ifndef judge
freopen("E:/yxc/in.txt", "r", stdin);
freopen("E:/yxc/out.txt", "w", stdout);
#endif
cin >> n;
init();
int a, b;
for (int i = 1; i < n; i++) {
cin >> a >> b;
add(a, b);
add(b, a);
}
dfs(1); //无向树是可以假定根为任何点的 这里假定为1
// for (int i = 1; i <= n; i++) cout << cnt[i] << endl;
for (int i = 2; i <= n; i++) {
//把该点删除之后得到的是
//该点的儿子构成的联通块 以及 根节点-它的儿子们联通块-1
int tres = 0; //当前的最大的联通块
int tcnt = 0;
for (int j = h[i]; j != -1; j = ne[j]) {
int k = e[j];
if (k == fa[i]) continue; //跳过父亲
tres = max(cnt[k], tres);
tcnt += cnt[k];
}
tres = max(tres, cnt[1] - tcnt - 1);
res = min(res, tres);
}
int tres = 0;
for (int j = h[1]; j != -1; j = ne[j]) {
int k = e[j];
tres = max(cnt[k], tres);
}
res = min(res, tres);
cout << res << endl;
return 0;
}