当前位置 博文首页 > Plus Ultra!:图论 —— 树的直径 及 其两种求法

    Plus Ultra!:图论 —— 树的直径 及 其两种求法

    作者:[db:作者] 时间:2021-09-21 21:05

    定义:

    树的直径,即 树上最远的两点的距离(即 树上最大距离),若树的边权全为 1 1 1,则树的直径即是 树上的最长链

    通常有两种树的直径的求法,时间复杂度均为 O ( n ) O(n) O(n)



    ①树形DP求树的直径

    改方法只需遍历一次,即可求得树的直径大小,但无法求得直径的具体路径

    选取任意结点为根遍历树,设 d [ i ] : d[i]: d[i]:表示结点 i i i为根的子树结点最远距离。

    则有:

    • u u u为根的子树结点最远距离 d [ u ] = max ? { d [ v ] + w u ? v }        v ∈ u d[u]=\max\{d[v]+w_{u-v}\}\;\;\;v\in u d[u]=max{d[v]+wu?v?}vu的子结点

    最后直径即为 根结点两个最远距离之和

    int d[maxn],len=0;
    void DP(int u,int pre)
    {
        d[u]=0;   //初始为0
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v,w=e[i].w;
            if(v==pre)
                continue;
            DP(v,u);
            len=max(len,d[u]+d[v]+w);  //更新直径
            d[u]=max(d[u],d[v]+w);
        }
    }
    


    ②两次DFS求直径

    该方法要遍历两次,第一次任选结点为根进行DFS,找到距离最远的结点;第二次以该距离最远的结点为根进行DFS,找到距离最远的结点两点距离即为直径大小,两点简单路径即为直径


    d i s t [ i ] : dist[i]: dist[i]表示 i i i结点到根结点的距离

    • 若要记录路径,可 对第二次DFS进行修改,因为 第一次DFS得到的距离最远结点一定为直径的一个端点,只要以其为根DFS找到距离最远的点(令一个端点)路径即为直径
    int dist[maxn],s,max_dist;
    void DFS(int u,int pre)
    {
        if(dist[u]>max_dist)
        {
            max_dist=dist[u];
            s=u;
        }
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v,w=e[i].w;
            if(v==pre)
                continue;
            dist[v]=dist[u]+w;
            DFS(v,u);
        }
    }
    int get_len()
    {
        max_dist=dist[1]=0;
        s=1;
        DFS(1,-1);
        max_dist=dist[s]=0;
        DFS(s,-1);
        return max_dist;
    }
    
    cs