https://www.acwing.com/problem/content/848/
模板题
给定一颗树,树中包含 n 个结点(编号 1∼n)和 n−1 条无向边。
请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。
重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值 最小,那么这个节点被称为树的重心。
(即,不包括本身的子树的大小)
输入格式
第一行包含整数 n,表示树的结点数。
接下来 n−1 行,每行包含两个整数 a 和 b,表示点 a 和点 b 之间存在一条边。
输出格式
输出一个整数 m,表示将重心删除后,剩余各个连通块中点数的最大值。
数据范围
1≤n≤105
输入样例
9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6
输出样例:
4
思想:递归;DFS求结点数
出口:无临近点,return 1
dp:所属结点的sum和
求出所有点,子树的大小r,n-sum(所有s的和再加1),保留最大的。
找到最小的情况
#include <algorithm>
#include <iostream>
#include <queue>
#include<map>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <cstring>
#include <cstdio>
#define _for(i,a,b) for(int i=a;i<b;i++)
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
const int N = 1e5 + 10;//数据范围
const int M = N * 2;//无向图:个节点至多对应2n-2条边
const int INF = 0x3f3f3f3f;
int n;
int h[N],e[M],ne[M],idx;
bool st[N];
int ans=INF;
void add(int a,int b){
e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
int dfs(int u){
st[u]=1;
int sum=1;
int re=0;
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(!st[j]){
st[j]=1;
int s=dfs(j);
sum+=s;
re=max(re,s);
}
}
re=max(re,n-sum);
ans=min(ans,re);
return sum;
}
int main(){
cin>>n;
mem(h,-1);
_for(i,0,n-1){
int a,b;
cin>>a>>b;
add(a,b),add(b,a);
}
dfs(1);
cout<<ans;
}