原题
刚看了一点图论…做一个笔记吧;
这个题思路很简单,主要是树的dfs的一个应用。
题目要求求树的重心,然后删去接着求剩下连通块中的最大值。
(重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。)
1.每一个连通块的节点数目应该等于它的
子
树
的
节
点
数
目
之
和
+
1
子树的节点数目之和 + 1
子树的节点数目之和+1.
2.如果节点x是重心的话,就可以依次以x的子节点出发遍历统计节点数而每次都可以根据1来统计.
这样一来就可以发现我们可以遍历每一个节点是不是重心来求答案了(从树的最下端开始求因为dfs是走到尽头才返回的)
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const ll maxn = 1e6 + 5;
int cnt = 1,head[maxn],book[maxn],a,b,n,ans = INF;
struct Node
{
int next,endd;
} Tree[maxn];
void add(int a, int b)
{
Tree[cnt].endd = b;
Tree[cnt].next = head[a];
head[a] = cnt++;
}
int dfs(int node)
{
//走过就标记
book[node] = 1;
int sum = 1,res = 0;
for(int i = head[node]; i != 0; i = Tree[i].next)
{
if(!book[Tree[i].endd])
{
//该颗子树的节点数用temp存
int temp = dfs(Tree[i].endd);
res = max(res,temp);
//所有子树的节点数用sum存
sum += temp;
}
}
//这里注意dfs走不到树的上端但是可以用 (总结点数 - 子树的节点数 - 1)来求
res = max(n - sum,res);
ans = min(res,ans);
//每次返回以该节点为根的数的节点数
return sum;
}
int main()
{
cin >> n;
for(int i = 1; i < n; i++)
{
cin >> a >> b;
add(a,b),add(b,a);
}
//从根开始
dfs(1);
cout << ans << endl;
return 0;
}