Luogu P3379 [template] nearest common ancestor (LCA) (tree chain segmentation)

Title Description

For example, given a tree with multiple forks, the nearest common ancestor of two specified points is requested.

I / O format

Input format:

 

The first row contains three positive integers N, M and S, which respectively represent the number of nodes in the tree, the number of queries and the serial number of the root node of the tree.

Next, each row of N-1 contains two positive integers x and y, indicating that there is a direct connection between X and Y nodes (data guarantee can form a tree).

Next, each row of row M contains two positive integers a and b, indicating the nearest common ancestor of query a and b nodes.

 

Output format:

 

The output contains M lines, and each line contains a positive integer, which is the result of each query in turn.

 

Example of input and output

Input example ා 1:copy
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
Output example:copy
4
4
1
4
4

Explain

Space time limit: 1000ms,128M

Data size:

For 30% data: n < = 10, m < = 10

For 70% of data: n < = 10000, m < = 10000

For 100% data: n < = 500000, m < = 500000

Example description:

The tree structure is as follows:

The first inquiry: the nearest common ancestor of 2 and 4, so it is 4.

The second inquiry: the nearest common ancestor of 3 and 2, so it is 4.

The third inquiry: the nearest common ancestor of 3 and 5, so it is 1.

The fourth inquiry: the nearest common ancestor of 1 and 2, so it is 4.

The fifth inquiry: the nearest common ancestor of 4 and 5, so it is 4.

So the output is 4, 4, 1, 4, 4 in turn.

 

 

LCA by tree chain partition

Keep jumping, jump to a heavy chain

Output on

Don't write line tree

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=2*1e6+10;
#define ls k<<1
#define rs k<<1|1
inline char nc()
{
    static char buf[MAXN],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    char c=nc();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
    while(c>='0'&&c<='9'){x=x*10+c-'0',c=nc();}
    return x*f;
}
struct node
{
    int u,v,nxt;
}edge[MAXN];
int head[MAXN];
int num=1;
void AddEdge(int x,int y)
{
    edge[num].u=x;
    edge[num].v=y;
    edge[num].nxt=head[x];
    head[x]=num++;
}
int fa[MAXN],deep[MAXN],tot[MAXN],son[MAXN],top[MAXN],cnt;
int dfs1(int now,int f,int dep)
{
    deep[now]=dep;
    fa[now]=f;
    tot[now]=1;
    int maxson=-1;
    for(int i=head[now];i!=-1;i=edge[i].nxt)
    {
        if(edge[i].v==f) continue;
        tot[now]+=dfs1(edge[i].v,now,dep+1);
        if(tot[edge[i].v]>maxson) maxson=tot[edge[i].v],son[now]=edge[i].v;
    }
    return tot[now];
}
void dfs2(int now,int topf)
{
    top[now]=topf;
    if(!son[now]) return ;
    dfs2(son[now],topf);
    for(int i=head[now];i!=-1;i=edge[i].nxt)
        if(edge[i].v!=son[now]&&edge[i].v!=fa[now])
            dfs2(edge[i].v,edge[i].v);
}
int LCA(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    return x;
}
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #else
    #endif
    memset(head,-1,sizeof(head));
    int N=read(),M=read(),root=read();
    for(int i=1;i<=N-1;i++) 
    {
        int x=read(),y=read();
        AddEdge(x,y);AddEdge(y,x);
    }
    dfs1(root,0,1);
    dfs2(root,root);
    while(M--)
    {
        int x=read(),y=read();
        printf("%d\n",LCA(x,y));
    }
    return 0;
}

Tags: C++

Posted on Mon, 04 May 2020 19:50:30 -0400 by Taneya