- 树的重心
给定一颗树,树中包含 n 个结点(编号 1∼n)和 n−1 条无向边。
请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。
重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。
输入格式
第一行包含整数 n,表示树的结点数。
接下来 n−1 行,每行包含两个整数 a 和 b,表示点 a 和点 b 之间存在一条边。
输出格式
输出一个整数 m,表示将重心删除后,剩余各个连通块中点数的最大值。
数据范围
1≤n≤10的5
输入样例
9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6
输出样例:
4
分析题目
- 明确树的重心是啥:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心
- 现在给我们一颗树,找到树的重心后删去求其剩余个个联通块中点数最大的。
- 非常明确了,首先运用邻接表储存该图
void add(int a,int b)//我前面哈希的文章中有讲这里就不展开了
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}//邻接表储存
- 运用dfs的方式删除当前节点后比较个个子树的点数大小选取最大的。
int dfs(int num)
{
book[num]=true;
int sum=1,ma=0;//当前节点相连点数之和,该节点删除点数最大的一块。
for(int k=h[num];k!=-1;k=ne[k])
{
int s=e[k];
if(!book[s])
{
int j=dfs(s);
ma=max(ma,j);
sum+=j;
}
}
ma=max(ma,l-sum);
ans=(ma,ans);
return sum;
}
代码在这
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e5+10,M=2*N;
int e[M],ne[M],h[N],idx;
int l,ans=N;
bool book[N];
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}//邻接表储存
int dfs(int num)
{
book[num]=true;
int sum=1,ma=0;
for(int k=h[num];k!=-1;k=ne[k])
{
int s=e[k];
if(!book[s])
{
int j=dfs(s);
ma=max(ma,j);
sum+=j;
}
}
ma=max(ma,l-sum);
ans=min(ans,ma);
return sum;
}
int main()
{
cin>>l;
memset(h,-1,sizeof(h));
for(int k=1;k<l;k++)
{
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
dfs(1);
cout<<ans<<endl;
return 0;
}