树的重心

树的重心

给定一颗树,树中包含n个结点(编号1~n)和n-1条无向边。

请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。

重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。

输入格式

第一行包含整数n,表示树的结点数。

接下来n-1行,每行包含两个整数a和b,表示点a和点b之间存在一条边。

输出格式

输出一个整数m,表示重心的所有的子树中最大的子树的结点数目。


非常经典的dfs遍历树的题目;

这道题充分说明了树和dfs的关系,递归生成树,然后还可以返回父节点的所有子树的值等等;

代码:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
//ios::sync_with_stdio(false);
using namespace std;
const int N=100010;
const int M=200100;
const LL mod=1e9+7;
int n;
int head[N];
struct Node{
	int to,nex;
}edge[N<<1];
int cnt;
void add(int p,int q){
	edge[cnt].to=q;
	edge[cnt].nex=head[p];
	head[p]=cnt++;
}
int mmax=1e9;//答案 
int dfs(int so,int fa){
	int sum=1;//so为父结点的子树的总结点数
	int ms=0;//子树的最大的结点数
	for(int i=head[so];~i;i=edge[i].nex){
		int v=edge[i].to;
		if(v==fa) continue;
		int s=dfs(v,so);
		ms=max(ms,s); //因为每个子树都是一个连通块
		sum+=s;
	}
	ms=max(ms,n-sum);
	mmax=min(mmax,ms);
	return sum;
}
int main(){
	ios::sync_with_stdio(false);
	memset(head,-1,sizeof(head));
	cin>>n;
	for(int i=1;i<=n-1;i++){
		int p,q;
		cin>>p>>q;
		add(p,q);
		add(q,p);
	}
	dfs(1,-1);
	cout<<mmax<<endl; 
	return 0;
}

更新:

知道了树的重心,还要知道树的重心的一些性质:

  1. 树中所有点到某个点的距离和中,到重心的距离和是最小的
  2. 把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上
  3. 一棵树最多有两个重心,且相邻

第一个性质特别重要;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值