0715-树的重心-POJ1655

本来呢,我是在看老师给的思考题--树的中心,然后莫名其妙就开始研究起树的重心了

不过先把思考题抬出来,下篇博客讲

思考题:求树的中心
树的中心:即求树中的点对最远距离最近。

问题:给你一棵有N个结点边权均为1的树,要求你找到树中的点,使得此点到树中的其它结点的最远距离最近。范围:N<=200000

------------------------------------------------------------------------------------------------------------------

还是讲讲树的重心吧,上题--点击打开链接

题意:给定一棵树,求树的重心的编号以及重心删除后得到的最大子树的节点个数size,如果size相同就选取编号最小的.(其实我觉得网上给的树的重心的定义还不如poj上的英文好懂,大家自己看着办)

这显然给出来的是一个无根树,那为了方便dp我们就把其转为有根树(随便逮一个点作为根)。然后对于每一个点而言,我们可以把和它有边连接的点分为两部分,父亲那儿一堆,儿子一堆,然后只用计算儿子那里的,再用n去减,就可以得到上面父亲的了,然后再取最大值,得到当前点的balance,就over了


#include <map>
#include <cstring>
#include <iostream>
#include<vector>
#include<cstdio>
#include<cmath>
#include<algorithm> 
#define maxn 20009
using namespace std;

vector<int> q[maxn];
int t,n;
int d[maxn],f[maxn];

int minn=maxn,num=maxn;
void dfs(int u,int fa){
	if(d[u]) return ;/////如果之前搜到过,就直接返回
	d[u]=1;
	int i,j,k,maxdown=-1,maxall;
	for(i=0;i<q[u].size();++i){
		int v=q[u][i];
		if(v!=fa){
			dfs(v,u);
			d[u]+=d[v];
			maxdown=max(maxdown,d[v]);//////儿子中的max
		}
	}
	maxall=max(maxdown,n-d[u]);//////u的儿子和u的父亲的max

	if(maxall<minn||maxall==minn&&num>u){//////////////////////////
		minn=maxall;
		num=u;
	}
}
int main()
{
	scanf("%d",&t);
	int i,j,k,tt;
	for(tt=1;tt<=t;++tt){
		for(i=0;i<=maxn;++i)
			q[i].clear();
		scanf("%d",&n);
		for(i=1;i<n;++i){
			int u,v;
			scanf("%d%d",&u,&v);
			q[u].push_back(v);
			q[v].push_back(u);
		}
		memset(d,0,sizeof(d));
		minn=maxn;num=maxn;/////////////一遇到多组数据的就一定要注意初始化
		dfs(1,-1);
		printf("%d %d\n",num,minn);
	}	
}

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/81046274