树的直径
Aug.3
树的直径:因为树是一个无环的图,对于一棵树的任意两个节点,它们的距离都是一定的,而树中所有简单路径(不知道森么意思的同学自行百度)的max值叫做树的直径;
Solution:方法十分简单,只需要把这棵树看成图,从图的任意节点u BFS整张图(树),找到距离u最远的节点v,再次BFS遍历整张图(树),找到距离v最远的节点w,dis(w,v)即为这个树的直径。
需要注意的是,当节点数n过大时,需要用到前向星(PS.我过两天会发一个关于前向星的文章,你们可以等等or自行百度)来存储整个树;
Prove: emmmmm推荐这个链接:
https://www.cnblogs.com/wuyiqi/archive/2012/04/08/2437424.html
废话不多说,上代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,w[2000010],head[2000010],max_len,p;//head[]也是前向星存储的一部分
struct hh
{
int x,y;//这里的.y一般都写作.to
}edge[2000010];//前向星存储
bool vis[2000010];//用来标记i节点是否遍历过
bool cmp(hh a,hh b)
{
if(a.x<b.x) return true;
if(a.x>b.x) return false;
if(a.y<b.y) return true;
return false;//前向星存储
}
void sch(int x,int len)//x为当前节点,len为dis(x,初始节点)
{
if(len>max_len){max_len=len;p=x;}//用max_len更新距离最大值,p用来更新最大值的节点x
for(int i=head[x];i<=head[x]+w[x]-1;i++)
if(!vis[edge[i].y]//如果没经过edge[i].y号节点
{
vis[edge[i].y]=true;//标记i号节点
sch(edge[i].y,len+1);//扩展下一步
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n-1;i++)
{
scanf("%d %d",&edge[i*2-1].x,&edge[i*2-1].y);
edge[i*2].x=edge[i*2-1].y;
edge[i*2].y=edge[i*2-1].x;//前向星存储
}
sort(edge+1,edge+2*n-1,cmp);//前向星存储
for(int i=1;i<=2*n-2;i++)
{
if(edge[i-1].x!=edge[i].x) head[edge[i].x]=i;
w[edge[i].x]++;//前向星存储
}
vis[1]=true;//先标记1号节点已经经过
sch(1,0);//因为从任意节点开始遍历都可以,这里就从1号开始遍历
memset(vis,false,sizeof(vis));
max_len=0;
vis[p]=true;//重置vis[],max_len
sch(p,0);//这里的p即为上文中的v号节点
printf("%d",max_len);
return 0;
}
我再说一句啊,同学们千万千万不要抄代码(虽然我写的不怎么好),不管是谁的代码,千万别复制粘贴,对自己没有一丁点的好处,实在记不住照着看几遍然后一个字一个字手敲进去,多敲几次就好多辣~~~
这篇文章多亏了chumeng同学鼎力相助(虽然他一直在我左边玩游戏)~~~~