【模板】最近公共祖先(LCA)
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入输出格式
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=500000,M<=500000
样例说明:
该树结构如下:

第一次询问:2、4的最近公共祖先,故为4。
第二次询问:3、2的最近公共祖先,故为4。
第三次询问:3、5的最近公共祖先,故为1。
第四次询问:1、2的最近公共祖先,故为4。
第五次询问:4、5的最近公共祖先,故为4。
故输出依次为4、4、1、4、4。
思路:
这道题是最近公共祖先的模板题。。。
很显然,先dfs跑一遍,再由深度浅的往根跳,枚举该点是否合法
那么一个一个往上跳吧?
看一看范围:500000!!!!
TLE的飞起
怎么优化呢?
倍增一下
往上一个成不成立?
不成立
2个呢?
4个呢?
终究会成立
时复大大下降
见代码:
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
struct ljb{
int from,to;
}tu[];
],xyg[],n,m,root,sd[],f[][],have[],s,t;
float bz;
void read(int &x)
{
;
x=;
char s=getchar();
')
{
if(s=='-')
{
f=-;
}
s=getchar();
}
')
{
x=x*+s-';
s=getchar();
}
x*=f;
}
void shd(int u,int h)
{
int ltt;
sd[u]=h;
;i<=bz;i++)
{
<<i))
{
break;
}
f[u][i]=f[f[u][i-]][i-];
}
int k=head[u];
)
{
ltt=tu[k].to;
if(!have[ltt])
{
have[ltt]=;
f[ltt][]=u;
shd(ltt,h+);
}
k=xyg[k];
}
}
int lca(int ltt,int kkk)
{
int lzn=sd[ltt];
int chen_ze=sd[kkk];
if(lzn!=chen_ze)
{
if(lzn<chen_ze)
{
swap(ltt,kkk);
swap(lzn,chen_ze);
}
int cha=lzn-chen_ze;
;i<=bz;i++)
{
<<i)&cha)
{
ltt=f[ltt][i];
}
}
}
if(ltt==kkk)
{
return kkk;
}
;
;i--)
{
)
{
continue;
}
if(f[ltt][i]==f[kkk][i])
{
continue;
}
else
{
ltt=f[ltt][i];
kkk=f[kkk][i];
}
}
];
}
int main()
{
read(n);
read(m);
read(root);
memset(head,-,sizeof(head));
memset(xyg,-,sizeof(xyg));
*(n-);
;i<=dsd;i+=)
{
read(s);
read(t);
tu[i].from=s;
tu[i].to=t;
tu[i+].from=t;
tu[i+].to=s;
xyg[i]=head[s];
head[s]=i;
xyg[i+]=head[t];
head[t]=i+;
}
bz=log(n)/log()+;
memset(have,,sizeof(have));
memset(sd,,sizeof(sd));
memset(f,-,sizeof(f));
have[root]=;
shd(root,);
;i<=n;i++)
{
;j<=bz;j++)
{
<<j))
{
break;
}
}
}
;i<=m;i++)
{
read(s);
read(t);
int y=lca(s,t);
printf("%d\n",y);
}
;
}
【模板】最近公共祖先(LCA)的更多相关文章
- [模板] 最近公共祖先/lca
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...
- Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)
Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...
- POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)
POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...
- POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...
- 【lhyaaa】最近公共祖先LCA——倍增!!!
高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...
- 最近公共祖先(LCA)模板
以下转自:https://www.cnblogs.com/JVxie/p/4854719.html 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖 ...
- HDU 2586 How far away ?(LCA模板 近期公共祖先啊)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...
- luogu3379 【模板】最近公共祖先(LCA) 倍增法
题目大意:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 整体步骤:1.使两个点深度相同:2.使两个点相同. 这两个步骤都可用倍增法进行优化.定义每个节点的Elder[i]为该节点的2^k( ...
- 最近公共祖先lca模板
void dfs(int x,int root){//预处理fa和dep数组 fa[x][0]=root; dep[x]=dep[root]+1; for(int i=1;(1<<i)&l ...
- 【洛谷 p3379】模板-最近公共祖先(图论--倍增算法求LCA)
题目:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 解法:倍增. 1 #include<cstdio> 2 #include<cstdlib> 3 #include ...
随机推荐
- javascript之DOM对象
document方法 document.createElement(Tag) :创建一个html标签对象 document.getElementById(ID) :获得指定ID值的对象 documen ...
- 一步步创建Qt Widget项目+TextFinder案例(摘自笔者2015年将出的《QT5权威指南》,本文为试读篇)
创建一个基于应用的QtWidget应用程序 这个手册描述了怎样使用QtCreater创建个一个小的Qt应用程序,Text Finder.它是Qt工具Text Finder例子的简写版本.这个应用 ...
- Shell脚本编程入门(一)
最近在学shell,记录一下. if语句的使用: 1.判断两个参数大小 #!/bin/sh #a test about if statement a=10 b=20 if [ $a -eq $b ]; ...
- 安卓服务Service详解
service(服务)是安卓中的四大组件之一,它通常用作在后台处理耗时的逻辑,与Activity一样,它存在自己的生命周期,也需要在清单文件中配置相关信息,本博客将对Service的各个知识点进行详细 ...
- 压力测试工具Ab简介
Apache安装包中自带的压力测试工具 Apache Benchmark(简称ab) 简单易用,这里就采用 ab作为压力测试工具了. 1.独立安装 通过 yum-utils中的yumdownload ...
- Android的ExpandableListView-android学习之旅(二十八)
ExpandableListView简介 ExpandableListView是ListView的子类,用法和ListView类似,ExpandableListView可以创建几个类别,每个类别下面又 ...
- Mpg123源代码详解
Mpg123与libmad一样,支持mpeg1,2,2.5音频解码.目前来看mpg123比libmad支持了网络播放功能.而且libmad基本上开源社区在2005年左右,基本停止更新,mpg123至今 ...
- SQLServer导出数据到MySQL
1从SQLServer导出数据 执行BCP: bcp "..." queryout "F:\test.txt" -c –S1.2.3.4 -Usa -P1111 ...
- pig简单的代码实例:报表统计行业中的点击和曝光量
注意:pig中用run或者exec 运行脚本.除了cd和ls,其他命令不用.在本代码中用rm和mv命令做例子,容易出错. 另外,pig只有在store或dump时候才会真正加载数据,否则,只是加载代码 ...
- design principle:java 回调与委派/委托机制
博客 design principle:模拟 android Button 控件点击事件 主要说了一下模拟 android 的 Listener 模式,其实这就是一种委派与回调机制的体现. 委派,也可 ...