最近公共祖先(Tarjin)

【模板】最近公共祖先(LCA)

题目描述

如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。

输入格式

第一行包含三个正整数 N , M , S N,M,S N,M,S,分别表示树的结点个数、询问的个数和树根结点的序号。

接下来 N − 1 N-1 N1 行每行包含两个正整数 x , y x, y x,y,表示 x x x 结点和 y y y 结点之间有一条直接连接的边(数据保证可以构成树)。

接下来 M M M 行每行包含两个正整数 a , b a, b a,b,表示询问 a a a 结点和 b b b 结点的最近公共祖先。

输出格式

输出包含 M M M 行,每行包含一个正整数,依次为每一个询问的结果。

样例 #1

样例输入 #1

5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5

样例输出 #1

4
4
1
4
4

提示

对于 30 % 30\% 30% 的数据, N ≤ 10 N\leq 10 N10 M ≤ 10 M\leq 10 M10

对于 70 % 70\% 70% 的数据, N ≤ 10000 N\leq 10000 N10000 M ≤ 10000 M\leq 10000 M10000

对于 100 % 100\% 100% 的数据, 1 ≤ N , M ≤ 500000 1 \leq N,M\leq 500000 1N,M500000 1 ≤ x , y , a , b ≤ N 1 \leq x, y,a ,b \leq N 1x,y,a,bN不保证 a ≠ b a \neq b a=b

样例说明:

该树结构如下:

第一次询问: 2 , 4 2, 4 2,4 的最近公共祖先,故为 4 4 4

第二次询问: 3 , 2 3, 2 3,2 的最近公共祖先,故为 4 4 4

第三次询问: 3 , 5 3, 5 3,5 的最近公共祖先,故为 1 1 1

第四次询问: 1 , 2 1, 2 1,2 的最近公共祖先,故为 4 4 4

第五次询问: 4 , 5 4, 5 4,5 的最近公共祖先,故为 4 4 4

故输出依次为 4 , 4 , 1 , 4 , 4 4, 4, 1, 4, 4 4,4,1,4,4

Java代码

import java.util.*;
import java.io.*;
class Point
{
    int y;
    int id;
    public Point(){}
    public Point(int y,int id)
    {
        this.y=y;
        this.id=id;
    }
}
public class Main
{
    public static int N=500010;
    public static int M=2*N;
    public static int n,m,s,idx;
    public static int[] h = new int[N];
    public static int[] e = new int[M];
    public static int[] ne = new int[M];
    public static int[] dist = new int[N];
    public static int[] p = new int[N];  //并查集
    public static int[] res = new int[N];
    public static int[] st = new int[N];
    public static ArrayList<ArrayList<Point>> query = new ArrayList<>();  //存询问
    public static void main(String[] args) throws IOException
    {
        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        in.nextToken();
        n=(int)in.nval;
        in.nextToken();
        m=(int)in.nval;
        in.nextToken();
        s=(int)in.nval;
        Arrays.fill(h,-1);
        for(int i=0;i<=n;i++)
            query.add(new ArrayList<>());
        for(int i=0;i<n-1;i++)  //建立边
        {
            in.nextToken();
            int a=(int)in.nval;
            in.nextToken();
            int b=(int)in.nval;
            add(a,b);
            add(b,a);
        }
        
        for(int i=0;i<m;i++)  //m组询问
        {
            in.nextToken();
            int a=(int)in.nval;
            in.nextToken();
            int b=(int)in.nval;
            if(a != b)
            {
                query.get(a).add(new Point(b,i));
                query.get(b).add(new Point(a,i));
            }
        }
        
        for(int i=1;i<=n;i++)  //初始化并查集
            p[i]=i;
            
        tarjan(s);
        
        for(int i=0;i<m;i++)
            out.println(res[i]);
            
        out.flush();
    }
    public static void add(int a,int b)
    {
        e[idx]=b;
        ne[idx]=h[a];
        h[a]=idx++;
    }
    public static void tarjan(int u)
    {
        st[u]=1;  //正在遍历
        for(int i=h[u];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(st[j]==0)
            {
                tarjan(j);
                p[j]=u;
            }
        }
        
        //此时已到叶节点
        for(Point point : query.get(u))
        {
            int y=point.y;
            int id=point.id;
            
            if(res[id]!=0)  continue;  //如果已经回答过
            
            if(st[y]==2)  //如果已经回溯过
                res[id]=find(y);
        }
        
        st[u]=2;
    }
    public static int find(int x)
    {
        if(p[x]!=x) p[x]=find(p[x]);
        return p[x];
    }
}

S u b t a s k # 0 Subtask \#0 Subtask#0 过掉了,但是 S u b t a s k # 1 Subtask \#1 Subtask#1 R E RE RE

相关推荐

  1. 最近公共祖先(LCA)

    2024-03-21 21:06:03       16 阅读
  2. 【模板】最近公共祖先(LCA)

    2024-03-21 21:06:03       13 阅读
  3. 最近公共祖先(LCA)主要算法:

    2024-03-21 21:06:03       35 阅读
  4. 最近公共祖先(lca)倍增算法【模板】

    2024-03-21 21:06:03       22 阅读
  5. 二叉搜索树的最近公共祖先【数据结构】

    2024-03-21 21:06:03       33 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-21 21:06:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-21 21:06:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-21 21:06:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-21 21:06:03       20 阅读

热门阅读

  1. 提高效率:Python电子邮件自动化进阶技巧

    2024-03-21 21:06:03       20 阅读
  2. openjudge 4.6贪心算法3528:最小新整数

    2024-03-21 21:06:03       18 阅读
  3. ONNX 的简介及应用

    2024-03-21 21:06:03       19 阅读
  4. 设计模式(行为型设计模式——观察者模式)

    2024-03-21 21:06:03       20 阅读
  5. 使用Docker创建Let‘s Encrypt SSL证书

    2024-03-21 21:06:03       17 阅读
  6. vue2知识总结

    2024-03-21 21:06:03       18 阅读
  7. 《牛客》-D小红统计区间(easy)

    2024-03-21 21:06:03       18 阅读
  8. c++ string怎么copy固定长度的数据

    2024-03-21 21:06:03       22 阅读
  9. Userar vr和3d技术如何结合融合

    2024-03-21 21:06:03       19 阅读