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之间的距离加出来,就是直径的距离。
至于为什么,我太菜了,我也不知道。但是这就是爆搜求直径的方法了。
树的直径是一个很基础的内容,一定要掌握下来哦!