hihoCoder挑战赛14 题目2:赛车 LCA

题意:幻想乡有一个赛车场。赛车场里有N个地点。同时地点之间还有单向的道路存在。
这些道路使得赛车场形成了一个外向树的结构。也就是说,道路将这N个地点连成了一个有根树。并且所有的边都是从父亲指向孩子的。
由于幽香喜欢刺激,每次她去赛车场都会从根节点出发,选择最长的一条路径来玩。
但是现在幽香感觉最长的路径还是太短了,她打算在赛车场里新建一条道路使得新的最长路径最长。
同时,如果道路形成了一个环,那么可能会出现交通事故,所以幽香新建的道路不能导致环的出现。
你能帮幽香算出新建一条道路后的最长路径吗?幽香知道根节点一定是1号点。

先求出最远的那个点,当然那个点肯定是叶子节点,然后再枚举其他叶子节点,计算从那个点到这个叶子节点能走的距离,要计算那个叶子节点和当前叶子节点的LCA,然后计算下距离加起来就行了。。

//author: CHC
//First Edit Time: 2015-08-30 20:10
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#include <limits>
using namespace std;
typedef long long LL;
const int MAXN=100000+1000;
const int INF = numeric_limits<int>::max();
const LL LL_INF= numeric_limits<LL>::max();
struct Edge {
    int to,next;
    Edge(){}
    Edge(int _to,int _next):to(_to),next(_next){}
}e[MAXN<<1];
int head[MAXN],tot;
int fa[MAXN][22],dis[MAXN],d[MAXN];
void init(){
    memset(head,-1,sizeof(head));
    tot=0;
}
void AddEdge(int u,int v){
    e[tot]=Edge(v,head[u]);
    head[u]=tot++;
}
void dfs(int cur,int f){
    for(int i=1;i<=20;i++)
        fa[cur][i]=fa[fa[cur][i-1]][i-1];
    for(int i=head[cur];~i;i=e[i].next){
        int to=e[i].to;
        if(to==f)continue;
        dis[to]=dis[cur]+1;
        d[to]=d[cur]+1;
        fa[to][0]=cur;
        dfs(to,cur);
    }
}
int lca(int a,int b){
    if(d[a]<d[b])swap(a,b);
    int x=d[a]-d[b],y=0;
    while(x){
        if(x&1)a=fa[a][y];
        x>>=1;
        ++y;
    }
    if(a==b)return a;
    for(int i=19;i>=0;i--){
        if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];
    }
    return fa[a][0];
}
int chu[MAXN];
int main()
{
    int n;
    while(~scanf("%d",&n)){
        init();
        memset(chu,0,sizeof(chu));
        for(int i=1,x,y;i<n;i++){
            scanf("%d%d",&x,&y);
            AddEdge(x,y);
            ++chu[x];
        }
        fa[1][0]=1;
        dis[1]=0;
        d[1]=0;
        dfs(1,-1);
        int maxn=0,maxu=1;
        for(int i=1;i<=n;i++){
            if(chu[i]==0&&dis[i]>maxn){
                maxn=dis[i];
                maxu=i;
            }
        }
        int ans=maxn;
        for(int i=1;i<=n;i++){
            if(chu[i]==0&&maxu!=i){
                int v=lca(maxu,i);
                ans=max(ans,maxn+dis[i]-dis[v]);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(树,LCA)