树链剖分求lca

以poj 1330为例;

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define LL long long
#define pi (4*atan(1.0))
#define eps 1e-8
#define bug(x)  cout<<"bug"<<x<<endl;
const int N=1e4+10,M=2e6+10,inf=1e9+10;
const LL INF=1e18+10,mod=1e9+7;

struct edge
{
    int v,next;
} edge[N<<1];
int head[N<<1],edg,id,n;
/// 树链剖分

int fa[N],dep[N],son[N],siz[N]; // fa父亲,dep深度,son重儿子,siz以该点为子树的节点个数
int a[N],ran[N],top[N],tid[N],du[N];  // tid表示边的标号,top通过重边可以到达最上面的点,ran表示标记tid
void init()
{
    memset(son,-1,sizeof(son));
    memset(head,-1,sizeof(head));
    memset(du,0,sizeof(du));
    edg=0;
    id=0;
}

void add(int u,int v)
{
    edg++;
    edge[edg].v=v;
    edge[edg].next=head[u];
    head[u]=edg;
}

void dfs1(int u,int fath,int deep)
{
    fa[u]=fath;
    siz[u]=1;
    dep[u]=deep;
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==fath)continue;
        dfs1(v,u,deep+1);
        siz[u]+=siz[v];
        if(son[u]==-1||siz[v]>siz[son[u]])
            son[u]=v;
    }
}

void dfs2(int u,int tp)
{
    tid[u]=++id;
    top[u]=tp;
    ran[tid[u]]=u;
    if(son[u]==-1)return;
    dfs2(son[u],tp);
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==fa[u])continue;
        if(v!=son[u])
            dfs2(v,v);
    }
}
int lca(int l,int r)
{
    while(top[l]!=top[r])
    {
        if(dep[top[l]]<dep[top[r]])swap(l,r);
        l=fa[top[l]];
    }
    if(dep[l]<dep[r])swap(l,r);
    return r;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        int n;
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
            du[v]++;
        }
        for(int i=1;i<=n;i++)
        if(!du[i])
        {
            dfs1(i,-1,1);
            dfs2(i,i);
            break;
        }
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",lca(l,r));
    }
    return 0;
}

 

posted @ 2017-07-24 11:19  jhz033  阅读(138)  评论(0编辑  收藏  举报