树的直径

给n个点和m条边,边的权值为1,求树的直径.

HihoCoder - 1050 树中的最长路(树的直径,dfs)

这道题有两种做法,第一中是官方做法,也就是这个题目中讲的做法,枚举每一个点作为转折点t,求出以t为根节点的子树中的‘最长路’以及与‘最长路’不重合的‘次长路’,用这两条路的长度之和去更新答案,那么最终的答案就是这棵树的最长路长度

另一种是做法就是找一个点开始dfs,然后找到一个最远的点,然后以这个点为根,再进行一遍dfs,然后以这个点求出的最长的长度就是最长路。

代码

官方解法

const int N=1e5+20;
int n;
int first[N],tot,ans;
struct edge
{
    int v,next;
} e[N*2];
void add_edge(int u,int v)
{
    e[tot].v=v;
    e[tot].next=first[u];
    first[u]=tot++;
}
void init()
{
    mem(first,-1);
    tot=0;
    ans=0;
}
int dfs(int u,int fa)
{
    int fir=0,sec=0,depth;
    for(int i=first[u]; ~i; i=e[i].next)
    {
        int v=e[i].v;
        if(v!=fa)
        {
            depth=dfs(v,u)+1;
            if(depth>fir)
            {
                sec=fir;
                fir=depth;
            }
            else if(depth>sec)
                sec=depth;
        }
    }
    ans=max(ans,fir+sec);
    return fir;
}
int main()
{
    int u,v;
    init();
    scanf("%d",&n);
    for(int i=1; i<=n-1; i++)
    {
        scanf("%d%d",&u,&v);
        add_edge(u,v);
        add_edge(v,u);
    }
    dfs(1,0);
    printf("%d\n",ans);
    return 0;
}

搜索解法

const int N=1e5+20;
int n;
int first[N],tot,maxdepth,root;
struct edge
{
    int v,next;
} e[N*2];
void add_edge(int u,int v)
{
    e[tot].v=v;
    e[tot].next=first[u];
    first[u]=tot++;
}
void init()
{
    mem(first,-1);
    tot=0;
    maxdepth=0;
    root=0;
}
void dfs(int depth,int u,int fa)
{
    if(depth>maxdepth)
    {
        maxdepth=depth;
        root=u;
    }
    for(int i=first[u]; ~i; i=e[i].next)
    {
        int v=e[i].v;
        if(v!=fa)
            dfs(depth+1,v,u);
    }
}

int main()
{
    int u,v;
    init();
    scanf("%d",&n);
    for(int i=1; i<=n-1; i++)
    {
        scanf("%d%d",&u,&v);
        add_edge(u,v);
        add_edge(v,u);
    }
    dfs(0,1,0);
    maxdepth=0;
    dfs(0,root,0);
    printf("%d\n",maxdepth);
    return 0;
}

results matching ""

    No results matching ""