树的直径与树的重心

树的直径

直径的性质:距离任意点最远的点一定是直径的一个端点,这个基于贪心求直径方法的正确性可以得出

方法:\(d_1,d_2\)分别表示距离一个点的最远距离和次远距离,求\(d_1+d_2\)的最大值

代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn=1e4+10;
int read(){
	int x=1,a=0;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') x=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){a=a*10+ch-'0';ch=getchar();}
	return x*a;
}
struct node{
	int to,next;
}ed[maxn*2];
int tot,head[maxn];
void add(int u,int to){
	ed[++tot].to=to;
	ed[tot].next=head[u];
	head[u]=tot;
}
int d;
int dfs(int x,int fa){
	int d1=0,d2=0;
	for (int i= head[x];i;i=ed[i].next){
		int to=ed[i].to;
		if(to==fa) continue;
		d=dfs(to,x)+1;
		if (d>d1) d2=d1,d1=d;
		else if (d>d2) d2=d;
	}
	d=max(d,d1+d2);
	return d1;
}
int n;
int main(){
	n=read();
	for (int i = 1;i <= n-1;i++){
		int x,y;
		x=read(),y=read();
		add(x,y),add(y,x);
	}
	dfs(1,-1);
	printf("%d\n",d);
	return 0;
}

树的重心

重心的性质:

以树的重心为根时,所有子树的大小都不超过整棵树大小的一半。

树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么到它们的距离和一样。

把两棵树通过一条边相连得到一棵新的树,那么新的树的重心在连接原来两棵树的重心的路径上。

在一棵树上添加或删除一个叶子,那么它的重心最多只移动一条边的距离。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int read(){
	int x=1,a=0;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') x=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){a=a*10+ch-'0';ch=getchar();}
	return x*a;
}
const int maxn=4e4+10;
struct node{
	int to,next;
}ed[maxn*2];
int tot,head[maxn];
void add(int u,int to){
	ed[++tot].to=to;
	ed[tot].next=head[u];
	head[u]=tot;
}
int t,n;
int size[maxn],weight[maxn],tree[2];
void dfs(int x,int fa){
	size[x]=1;weight[x]=0;
	for (int i = head[x];i;i=ed[i].next){
		int to=ed[i].to;
		if (to==fa) continue;
		dfs(to,x);
		size[x]+=size[to];
		weight[x]=max(size[to],weight[x]);
	}
	weight[x]=max(weight[x],n-size[x]);
	if (weight[x]<=n/2) tree[tree[0]!=0]=x;
}
int main(){
	t=read();
	while(t--){
		memset(head,0,sizeof(head));
		memset(ed,0,sizeof(ed));
		memset(size,0,sizeof(size));
		memset(weight,0,sizeof(weight));
		tree[0]=tree[1]=0;
		n=read();
		for (int i = 1;i <= n-1;i++){
			int x,y;
			x=read(),y=read();
			add(x,y),add(y,x);
		}
		dfs(1,-1);
		printf("%d %d",tree[0],weight[tree[0]]);
		putchar('\n');
	}
	return 0;
}
posted @ 2020-10-20 07:15  小又又  阅读(103)  评论(0编辑  收藏  举报