[吼吼]加工树枝

【描述】

Dragon同学一天捡到了一根非常非常巨大的树枝,于是同学就想啊,如果把这根树枝多余的分叉剔掉最后剩下一根没有分叉的木棍,用它自卫就没人敢欺负我们科学家了呀:)

你的任务是,对给定树枝,求出它包含的最长木棍。

【输入格式】

第一行一个正整数n,表示顶点数,顶点从1至n编号。

然后n – 1行每行两个正整数u, v表示u, v之间有一条边,每条边的长度为1。

保证输入的是一棵树。

【输出格式】

只有一行,表示给定树的最长链长度。

【样例输入】

5

1 2

1 3

1 4

1 5

【样例输出】

2

【分析】

很明显,求树中的最长链。设f[i]是i的子树中最远的点到自己的距离,p[i]是第二远的点到自己的距离。那么所有的点钟最大的f[i]+p[i]就是答案。

第一次写——临边表。显然存不下。

第二次写——模拟链表。用的递归造树,爆掉。

想到了要用手工的栈。

可是我不知道怎么写囧。

于是看了标程。

原来还可以这么构树!!!

原来手工栈这么写!!!

顿悟。

第三次——AC。

#include <stdio.h>

#include <stdlib.h>

#define maxn 1000010



int f[maxn];

int father[maxn],str[maxn];

struct ss

{

       int num,next;

} a[maxn];

int tot,n,u,v,p,ans;

int c[maxn],deep[maxn],sta[maxn],top,e[maxn],te;



void ins(int x,int y)

{

     a[++tot].num=y;

     a[tot].next=str[x];

     str[x]=tot;

}



int cmp(const void*a,const void*b)

{

    int c=*(int*)a,d=*(int*)b;

    if (deep[c]<deep[d]) return -1;

    if (deep[c]>deep[d]) return 1;

    return 0;

}



int main()

{

    freopen("tree.in","r",stdin);

    freopen("tree.out","w",stdout);

    

    scanf("%d",&n);

    for (int i=1;i<n;++i)

    {

        scanf("%d%d",&u,&v);

        ins(u,v);

        ins(v,u);

    }

    

    sta[0]=1;

    e[0]=str[1];

    father[1]=0;

    while (top>=0)

    {

          te=e[top];

          if (!te) --top;

          else

          {

              v=sta[top];

              u=a[te].num;

              e[top]=a[te].next;

              if (u!=father[v])

              {

                          sta[++top]=u;

                          e[top]=str[u];

                          deep[u]=deep[v]+1;

                          father[u]=v;

              }

          }

    }

    

    for (int i=1;i<=n;++i) c[i]=i;

    deep[0]=-1;

    qsort(c,n+1,sizeof(int),cmp);

    for (int i=n;i>0;--i)

    {

        u=c[i];

        te=str[u];

        if (!te) continue;

        p=0;

        do

        {

                 v=a[te].num;

                 if (father[u]!=v)

                    if (f[v]+1>f[u])

                    {

                                  p=f[u];

                                  f[u]=f[v]+1;

                    }

                    else 

                         if (f[v]+1>p) p=f[v]+1;

                 te=a[te].next;

        }

        while (te);

        if (f[u]+p>ans) ans=f[u]+p;

    }

    

    printf("%d\n",ans);

    

    return 0;

}



 

 

你可能感兴趣的:(树)