LCA Tarjan

//LCA
//Tarjan 离线 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxn 500001
using namespace std;
int n,m,root,cnt,lca[maxn],head[maxn],jdg[maxn],fa[maxn],set[maxn];//set并查集 
int cntget,headget[maxn];
struct uio{
    int to,next;
}edge[2*maxn];
struct oiu{
    int to,next,num;//num表示第几次询问 
}get[2*maxn]; 
inline int read()
{
    int k=0,f=1;
    char c=getchar();
    for(; !isdigit(c);c = getchar()) 
        if(c=='-')
            f = -1;
    for(; isdigit(c);c = getchar())
        k=k*10+c-'0';
    return k*f;
}
void add(int u,int v)
{
    edge[++cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt;
}
void addget(int u,int v,int w)
{
    get[++cntget].to=v;
    get[cntget].next=headget[u];
    headget[u]=cntget;
    get[cntget].num=w;//记录是第几次询问 
}
int find(int x)
{
    if(x==set[x])
        return x;
    return set[x]=find(set[x]);
} 
void tarjan(int x)
{
    jdg[x]=1;
    set[x]=x;
    for(int i=head[x];i!=-1;i=edge[i].next)
        if(!jdg[edge[i].to])
        {
            tarjan(edge[i].to);
            set[edge[i].to]=x;
        }
    for(int i=headget[x];i!=-1;i=get[i].next)
        if(jdg[get[i].to]==1)
            lca[get[i].num]=find(get[i].to);
}
int main()
{
//    n=read();
//    m=read();
//    root=read();
    scanf("%d%d%d",&n,&m,&root);
    memset(head,-1,sizeof(head));
    memset(headget,-1,sizeof(headget));
    for(int i=1;i<=n-1;i++)
    {
        int u,v;
//        int u=read();
//        int v=read();
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    for(int i=1;i<=m;i++)
    {
        int u,v;
//        int u=read();
//        int v=read();
        scanf("%d%d",&u,&v);
        addget(u,v,i);
        addget(v,u,i);
    }
    tarjan(root);
    for(int i=1;i<=m;i++)
        printf("%d\n",lca[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/water-radish/p/9280511.html
今日推荐