1. 程式人生 > >codevs——1814 最長鏈

codevs——1814 最長鏈

時間 重復 body input for set diamond fault output

1814 最長鏈

時間限制: 1 s 空間限制: 256000 KB 題目等級 : 鉆石 Diamond 題目描述 Description

現給出一棵N個結點二叉樹,問這棵二叉樹中最長鏈的長度為多少,保證了1號結點為二叉樹的根。

輸入描述 Input Description

輸入的第1行為包含了一個正整數N,為這棵二叉樹的結點數,結點標號由1至N。

接下來N行,這N行中的第i行包含兩個正整數l[i], r[i],表示了結點i的左兒子與右兒子編號。如果l[i]為0,表示結點i沒有左兒子,同樣地,如果r[i]為0則表示沒有右兒子。

輸出描述 Output Description

輸出包括1個正整數,為這棵二叉樹的最長鏈長度。

樣例輸入 Sample Input

5

2 3

4 5

0 6

0 0

0 0

樣例輸出 Sample Output

4

數據範圍及提示 Data Size & Hint

【樣例說明】

  4-2-1-3-6為這棵二叉樹中的一條最長鏈。

【數據規模】

對於10%的數據,有N≤10;

對於40%的數據,有N≤100;

對於50%的數據,有N≤1000;

對於60%的數據,有N≤10000;

對於100%的數據,有N≤100000,且保證了樹的深度不超過32768。

【提示】

關於二叉樹:

二叉樹的遞歸定義:二叉樹要麽為空,要麽由根結點,左子樹,右子樹組成。左子樹和右子樹分別是一棵二叉樹。

請註意,有根樹和二叉樹的三個主要差別:

1. 樹的結點個數至少為1,而二叉樹的結點個數可以為0;

2. 樹中結點的最大度數沒有限制,而二叉樹結點的最大度數為2;

3. 樹的結點無左、右之分,而二叉樹的結點有左、右之分。

關於最長鏈:

最長鏈為這棵二叉樹中一條最長的簡單路徑,即不經過重復結點的一條路徑。可以容易證明,二叉樹中最長鏈的起始、結束結點均為葉子結點。

樹的直徑裸題(說白了就是兩次dfs)

做法:

首先,我們先隨便找一個點為各節點對整棵樹進行一下dfs,求出離這個點最遠的節點t

然後,我們在以t點為根節點對整棵樹進行一下dfs,求出這個點最遠的節點m

這樣我們就稱tm是這棵樹的直徑!

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 110000
using namespace std;
bool vis[N];
int n,m,x,y,s,t,tot,fa[N],head[N],deep[N],ans;
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1; ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0; ch=getchar();}
    return x*f;
}
struct Edge
{
    int to,next,from;
}edge[N<<1];
int add(int x,int y)
{
    tot++;
    edge[tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot;
}
void dfs(int x)
{
    for(int i=head[x];i;i=edge[i].next)
    {
        int to=edge[i].to;
        if(!vis[to]&&fa[x]!=to)
        {
            fa[to]=x;
            vis[to]=true;
            deep[to]=deep[x]+1;
            dfs(to);
            vis[to]=false;
        }
    }
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        x=read(),y=read();
        if(x) add(x,i),add(i,x); 
        if(y) add(y,i),add(i,y);
        m=max(m,max(x,y));
    }
    s=1;deep[1]=1;dfs(1);
    for(int i=1;i<=m;i++)
     if(deep[i]>deep[s]) s=i;
    memset(fa,0,sizeof(fa));
    memset(deep,0,sizeof(deep));
    memset(vis,0,sizeof(vis));
    deep[s]=1;dfs(s);t=s;
    for(int i=1;i<=m;i++)
     if(deep[i]>deep[t]) t=i;
    ans=deep[t]-1;
    printf("%d",ans);
    return 0;
}

codevs——1814 最長鏈