最近公共祖先(LCA)模板

最近公共祖先(LCA)模板

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

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

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

 

输出格式:

 

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

输入样例#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

 

模板:时间复杂度nlogn

 

#include<iostream>
#include<cstdio>
using namespace std;
struct yyy{
       int t,
       nex;
}e[2 * 500001];
int deepth[500001], fa[500001][22], lg[500001], head[500001];
int tot;
void add(int x, int y) //邻接表存树
{
       e[++tot].t = y;
       e[tot].nex = head[x];
       head[x] = tot;
}
void dfs(int f, int fath)
{
       deepth[f] = deepth[fath] + 1;
       fa[f][0] = fath;
       for (int i = 1; (1 << i) <= deepth[f]; i++)
              fa[f][i] = fa[fa[f][i - 1]][i - 1];
       for (int i = head[f]; i; i = e[i].nex)
       if (e[i].t != fath)
              dfs(e[i].t, f);
}
int lca(int x, int y)
{
       if (deepth[x]<deepth[y])
              swap(x, y);
       while (deepth[x]>deepth[y])
              x = fa[x][lg[deepth[x] - deepth[y]] - 1];
       if (x == y)
              return x;
       for (int k = lg[deepth[x]]; k >= 0; k--)
       if (fa[x][k] != fa[y][k])
              x = fa[x][k], y = fa[y][k];
       return fa[x][0];
}
int n, m, s;//n节点,m查询,s边数
void init()
{
       scanf("%d%d%d", &n, &m, &s);
       for (int i = 1; i <= n - 1; i++)
       {
              int x, y;  scanf("%d%d", &x, &y);
              add(x, y); add(y, x);
       }
       dfs(s, 0);
       for (int i = 1; i <= n; i++)
              lg[i] = lg[i - 1] + (1 << lg[i - 1] == i);
}
 
int main()
{
       init();
       for (int i = 1; i <= m; i++)
       {
              int x, y;  scanf("%d%d", &x, &y);
              printf("%d\n", lca(x, y));
       }
 
       return 0;
}

 

转载于:https://www.cnblogs.com/ALINGMAOMAO/p/9643481.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101426.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 拦截器「建议收藏」

    拦截器「建议收藏」11.拦截器11.1拦截器概述SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。*

    2022年7月3日
    24
  • mse均方误差计算公式推导_误差函数erf是怎么算出来的

    mse均方误差计算公式推导_误差函数erf是怎么算出来的 

    2022年9月30日
    0
  • linux nginx启动停止命令_nginx无法启动

    linux nginx启动停止命令_nginx无法启动目录一、启动/usr/local/nginx/sbin/nginx-c/usr/local/nginx/conf/nginx.conf二、停止1、从容停止(1)查看进程号:ps-ef|grepnginx(2)杀死进程:kill-quitxxxx2、快速停止(1)查看进程号:ps-ef|grepnginx(2)杀死进程:kill-termxxxx/kill-intxxxx3、强制停止:pkill-9nginx三、重启1…

    2022年8月13日
    3
  • windows server2003 web服务器搭建

    windows server2003 web服务器搭建在控制面板中点击添加或删除程序,打开如下界面:勾选并打开应用程序服务器-Internet信息服务(IIS)-万维网服务依次点击确定后,开始下载服务,完成后打开IIS管理器然后进行如下设置在主目录下创建一个文本文档,输入内容,并保存为index.htm打开浏览器,输入IP地址,即可看到刚才输入的内容用物理机访问同理…

    2022年5月27日
    29
  • C/C++中static变量和static函数的用法

    C/C++中static变量和static函数的用法静态成员数据和静态成员函数1.C中静态数据和静态函数的用法C语言中定义一个静态变量和静态函数主要是为了满足某个文件的需求比如我们在文件List.c中定义staticintcount=0;//静态变量staticintget_last_node(List*Head)

    2022年7月16日
    125
  • 安卓broadcastreceiver_Android手电筒原理

    安卓broadcastreceiver_Android手电筒原理目录BroadcastReceiver概述BroadcastReceiver分类registerReceiver流程图源码解析总结1.BroadcastReceiver概述广播作为四大组件之一,在平时开发过程中会大量使用到,使用方式也是多种多样的,既可以自己在manifest中注册,也可以在java代码中动态注册,既可以接收由系统发出的广播,也可以接受自己定义并发送的广播。广播…

    2022年9月12日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号