树的基础:树的直径

Dev.C++树是一种特殊的图,有一些特殊的性质,直径就是其一。直径可以用2次爆搜或树形dp来求解。这里选用的是2次dfs
这次,我不得不结合代码来解释了。

#include<bits/stdc++.h>
#define MAXN 100100
using namespace std;
int head[MAXN],n,cnt,maxv,maxdis;//从左往右:head,该树有n条边,cnt,maxv离原点最远的点,maxdis是直径的长度
struct edge
{
	int nxt,to,w;
}e[4*MAXN];
void add(int u,int v)
{
	e[++cnt].nxt=head[u];
	e[u].to=v;
	head[u]=cnt;
}
void dfs(int u,int f,int dis)//u为这次搜索的原点,f是他的父亲,dis是u离原原点的距离
{
	if(maxdis<dis)//第二次爆搜时当已算出直径比原点到远点距离短时,更新直径
	{
		maxdis=dis;
		maxv=u;//更新maxv
	}
	for(int i=head[u];i!=0;i=e[i].nxt)
	{
		int v=e[i].to,w=e[i].w;//方便使用
		if(v==f)continue;//当e[i].to即原点指向的点是他爸时,如果再跑,就往回跑了,要continue掉,不然会死递归
		dfs(v,u,dis+w);//以这次原点他孩子(不会出现他爸,上面有特判)为原点,这次原点为父亲,向下扩增
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);//建双向边
	}
	dfs(1,-1,0);
	maxdis=0;
	dfs(maxv,-1,0);
	cout<<maxdis<<endl;
	return 0;
}

代码那里有解释,我不解释代码了。解释解释思想。


在树上任意找一点u,找到离这一点最远的点maxv。
再以maxv为u,找到离maxv最远的点。在寻找过程中,将第二个u和第二个maxv之间的距离加出来,就是直径的距离。
至于为什么,我太菜了,我也不知道。但是这就是爆搜求直径的方法了。


树的直径是一个很基础的内容,一定要掌握下来哦!

posted @ 2020-10-07 17:08  riced  阅读(233)  评论(1编辑  收藏  举报