hihocoder1224 賽車(樹的深度相關)

bigbigship發表於2015-08-31

題目連線:傳送門 


題意:

給你一棵樹,然後加一條邊,加的這條邊不能使樹成環,求加邊後從根節點出發的最長的路徑。


分析:

如果可以加邊的話那麼這兩個鏈一定是某個節點的最長鏈與次長鏈,然後一邊dfs處理出所有的節點的深度,然後再一遍dfs求出所有點的最長鏈的長度與次長鏈的長度,然後列舉節點就可以了。


程式碼如下:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;

const int maxn = 1e5+10;

vector<int > vc[maxn];

int dept[maxn];
int mmax;

void init(){
    for(int i=0;i<maxn;i++){
        vc[i].clear();
    }
    mmax=0;
}

void dfs(int u,int dep){
    dept[u]=++dep;
    mmax = max(dep,mmax);
    for(int i=0;i<vc[u].size();i++){
        int v=vc[u][i];
        dfs(v,dep);
    }
}

int m[maxn][2];

int slove(int u){
    if(m[u][0]) return m[u][0];
    int m1=dept[u],m2=0;
    for(int i=0;i<vc[u].size();i++){
        int tmp = slove(vc[u][i]);
        if(tmp<=m1&&tmp>m2&&m1!=dept[u]) m2=tmp;
        if(tmp>m1){
            if(m1!=dept[u])
                m2=m1;
            m1=tmp;
        }
    }
    m[u][0]=m1;
    m[u][1]=m2;
    return m1;
}

int main()
{
    int n;
    while(~scanf("%d",&n)){
        init();
        for(int i=0;i<n-1;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            vc[u].push_back(v);
        }
        memset(m,0,sizeof(m));
        dfs(1,0);
        slove(1);
        int ans = 0;
        for(int i=1;i<=n;i++){
            if(m[i][1])
                ans=max(ans,m[i][0]-1+m[i][1]-dept[i]);
        }
        if(!ans) printf("%d\n",mmax-1);
        else printf("%d\n",ans);
    }
    return 0;
}

/***
10
1 2
2 3
3 7
3 8
8 10
2 4
4 5
5 6
6 9
***/


相關文章