AcWing 846. 树的重心
原题链接
简单
作者:
满目星河_0
,
2021-03-31 12:33:23
,
所有人可见
,
阅读 245
带注释(超详细)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10,M=2*N;
int n,idx;
int ans=N;//存储剩余各个连通块中点数的最大值。
int h[N],e[M],ne[M];
//h表示各个单链表的头节点。
//e数组用来存储单链表各个节点对应的值
//ne用来存储当前节点的下一个节点是哪一个
//idx相当于单链表的指针
int used[N];//表示这个节点是否被使用过
void add(int a,int b){
e[idx]=b;//创建一个新的节点是idx,它的值是b
ne[idx]=h[a];//将这个节点指向h
h[a]=idx++; //再将h指向新的节点
//用数组来模拟链表,相当于利用数组之间的赋值来代替真实的链表的指针。
}
int dfs(int u){
int res=0,sum=1;
used[u]=1; //标记当前节点已经被遍历过
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i]; //i是节点的名字(idx),而e[i]才是这个节点的值。
if(!used[j]){
int s=dfs(j);
res=max(res,s);//res表示删除这个节点u之后的以这个节点为起点的最大连通块的大小
sum+=s;//sum表示以u为根的树的节点数
}
}
res=max(res,n-sum);//res连通块数的最大值,n-sum表示剩下的部分
ans=min(res,ans);//ans表示各个连通块中点数的最大值。
return sum;
}
int main(){
cin>>n;
memset(h,-1,sizeof(h));
int a,b;
for(int i=0;i<n-1;i++){
cin>>a>>b;
add(a,b);//无向图要add两次
add(b,a);
}
dfs(1);
cout<<ans;
return 0;
}