*倍增LCA:

  设$f[u][k]$表示u的$2^k$辈祖先,即从$u$向根节点走$2^k$步到达的节点,特别的,若该节点不存在,则$f[u][k]$=0.$f[u][0]$就是$x$的父亲节点。因为$u$向根节点$2^k$$\rightarrow$向根节点走$2^{k-1}$,再走$2^{k-1}$步。所以对于 k∈ [1,logn] ,有$f[u][k]=f[f[u][k-1]]]k-1]$。$f$数组利用了递推的思想。递推式为$f[u][k]=f[f[u][k-1]][k-1]$。因此,我们可以对树进行DFS

 inline void Deal_first(int u,int fa)
{
dep[u]=dep[fa]+;
for(int i=;i<;i++)
f[u][i+]=f[f[u][i]][i];
for(int i=head[u];i;i=t[i].nex)
{
int v=t[i].to;
if(v==fa) continue;
f[v][]=u;
Deal_first(v,u);
}
return;
}

①设$dep[x]$表示$x$的深度。那么设$dep[x]\ge dep[y]$。(否则可交换$x,y$)

②利用二进制拆分的思想,把$x$向上调整到与$y$同一深度。即:依次尝试从$x$向上走$k$=$2^{logn}……2^1 ,2^0$步,若到达的点比$y$深,则令$x=f[x][k]$

③若此时$x=y$,则说明已经找到了$LCA$,两点的$LCA$就等于$y$。

④若此时的 $x$ ≠ $y$ ,那么 $x$,$y$ 同时向上调整,并保持深度一致且二者不会相会。依次尝试把 $x$, $y$ 同时向上走$k$=$2^{logn}……2^1 ,2^0$步,若$f[x][k]$≠ $f[y][k]$,则令$x=f[x][k],y=f[y][k]$。

⑤此时 $x$,$y$ 必定只差一步就相会了,他们的父节点 $f[x][0]$就是 $LCA$。

 #include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define maxn 501000
int n,m,s;
int dep[maxn<<];
int f[maxn<<][];
int head[maxn<<],cnt=;
struct hh
{
int nex,to;
}t[maxn<<];
inline void add(int nex,int to)
{
t[++cnt].nex=head[nex];
t[cnt].to=to;
head[nex]=cnt;
}
inline void Deal_first(int u,int fa)
{
dep[u]=dep[fa]+;
for(int i=;i<;i++)
f[u][i+]=f[f[u][i]][i];
for(int i=head[u];i;i=t[i].nex)
{
int v=t[i].to;
if(v==fa) continue;
f[v][]=u;
Deal_first(v,u);
}
return;
}
inline int LCA(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=;i>=;i--)
{
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
if(x==y) return x;
}
for(int i=;i>=;i--)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][];
}
inline int read()
{
int kr=,xs=;
char ls;
ls=getchar();
while(!isdigit(ls))
{
if(!(ls^))
kr=-;
ls=getchar();
}
while(isdigit(ls))
{
xs=(xs<<)+(xs<<)+(ls^);
ls=getchar();
}
return xs*kr;
}
int main()
{
int x,y;
n=read();m=read();s=read();
for(int i=;i<n;i++)
{
x=read();y=read();
add(x,y);
add(y,x);
}
Deal_first(s,);
for(int i=;i<=m;i++)
{
x=read();y=read();
printf("%d\n",LCA(x,y));
}
return ;
}

LCA--P3379 【模板】最近公共祖先(LCA)的更多相关文章

  1. [模板] 最近公共祖先/lca

    简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...

  2. HDU 2586 How far away ?(LCA模板 近期公共祖先啊)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...

  3. Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)

    Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...

  4. POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)

    POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...

  5. POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)

    POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...

  6. 【lhyaaa】最近公共祖先LCA——倍增!!!

    高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...

  7. 【洛谷 p3379】模板-最近公共祖先(图论--倍增算法求LCA)

    题目:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 解法:倍增. 1 #include<cstdio> 2 #include<cstdlib> 3 #include ...

  8. 最近公共祖先(LCA)模板

    以下转自:https://www.cnblogs.com/JVxie/p/4854719.html 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖 ...

  9. luogu3379 【模板】最近公共祖先(LCA) 倍增法

    题目大意:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 整体步骤:1.使两个点深度相同:2.使两个点相同. 这两个步骤都可用倍增法进行优化.定义每个节点的Elder[i]为该节点的2^k( ...

  10. 最近公共祖先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 ...

随机推荐

  1. PHP使用ElasticSearch做搜索

    PHP 使用 ElasticSearch 做搜索 https://blog.csdn.net/zhanghao143lina/article/details/80280321 https://www. ...

  2. python反序列化漏洞

    原理在网页源码中如果出现将用户输入数据进行反序列化当成参数输出时,出现漏洞,可造成任意命令执行例如网页源码try:       become = self.get_argument('become') ...

  3. Codeforces 459E Roland and Rose

    本以为是个树形DP,按照树形DP的方法在那里dfs,结果WA到死,因为它存在有向环,不是树,凡是存在环的情况切记不要用树形的方法去做 题目的突破点在于将边排完序之后,用点表示以该点为边结尾的最大长度, ...

  4. mysql sql语句不同平台上大小写区分

  5. 针对Quartus IP Core的MIF文件格式小记

    Quartus里面的ROM IP核进行内容分配,需要在Wizard里面指定.mif文件. 本文有关细节和详细说明,请参照Quartus Prime 帮助文档v15.1 一个常见的mif文件如下所示: ...

  6. 12 MySQL存储过程与函数

    存储过程和函数     存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合.     调用存储过程和函数可以简化应用开发人员的工作,减少数据在数据库和应用服务器之间的传输,提高数据处理 ...

  7. NO4 find&mv-&-特殊符号..和.

    问题七:退到上一级目录,删除data目录. 解答:cd ..或cd ../        rm -r data或rmdir data#空目录就不需要带-rf,杀鸡不用宰牛刀,rmdir基本要淘汰的命令 ...

  8. duilib+cef自定义浏览器控件编译错误

    新版博客已经搭建好了,有问题请访问 htt://www.crazydebug.com 公司二期好主播项目,决定用duilib开发界面,且从ie内核换成谷歌内核 再用duilib自定义一个Browser ...

  9. Spark tungsten 项目阅读笔记

    Spark tungsten 项目阅读笔记 Spark tungsten 项目的宣言就是:Bringing Apache Spark closer Bare Metal. 我的理解就是不要让硬件成为S ...

  10. pl/sql远程连接oracle数据库乱码

    1. --在PLSQL Developer中查询select userenv('language') from dual ; 我的查询结果为:AMERICAN_AMERICA.ZHS16GBK 2.新 ...