我们怎么考虑这个树的重心这题目?
以每个节点为考虑对象,我们需要算出什么?
首先就是每个节点的子树的最大值,这还就是我们还没有考虑上面的子树的情况
题目要求的是去掉这个重心之后剩余连通块中点的最大值
那么这个点上方的点是什么情况?
这个点上面的点就是总的点数减去包括这个点的所有子树的点剩余的点啊
所以我们要维护什么值?
其一是所有子树中的最大值,还有总的结点数
怎么更新?
搜到子节点之后向上返回呗
但是注意这要是无向边
不然就没法搜到上面点的情况
我们先记录每个点的sum值首先是1
然后开始深搜
搜到底之后把子节点的值累加到根节点的总点数中去
但是什么时候统计子节点的最大值呢
我们没搜到一个结点就需要更新一次
然后我们还需要考虑一件事
我们怎么得出并更新这个节点上面的值?
上面节点的数量就是总的结点的数目减去这个结点的总的子树的大小
也就是n-sum
最后我们要统计的是整个树中子连通块的最小值
也就是 ans = min(ans,max(size,n-sum))
注意一定要取最大值
测试样例:
9
1 4
1 2
2 6
2 5
6 3
6 7
7 9
7 8
输出结果:4
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 200100;
ll n,st[N];
ll e[N],ne[N],h[N],idx;
ll ans = 0x3f3f3f3f;
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
ll dfs(int u)
{
ll sum = 1;
ll size = 1;
st[u] = 1;
for(int i=h[u];~i;i=ne[i])
{
int j = e[i];
if(!st[j])
{
ll s = dfs(j);
sum += s;
size = max(size,s);
}
}
ans = min(ans,max(size,n-sum));
return sum;
}
int main()
{
cin>>n;
memset(h,-1,sizeof h);
for(int i=1;i<=n-1;i++)
{
int a,b;
cin>>a>>b;
add(a,b);add(b,a);
}
dfs(1);
cout<<ans<<endl;
return 0;
}
要加油哦!!!