树的直径

树的直径
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同学鼎力相助(虽然他一直在我左边玩游戏)~~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值