*倍增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. 从三星官方uboot开始移植

    移植前的准备 下载 android_uboot_smdkv210.tar.bz2 这个文件 开始移植 本人使用的开发板是九鼎的 x210,在三星 uboot 的主 Makefile 中找到了类似的 s ...

  2. face_recognition实时人脸识别

    具体安装移步:https://www.cnblogs.com/ckAng/p/10981025.html 更多操作移步:https://github.com/ageitgey/face_recogni ...

  3. 【转载】UnityWebRequest的初步使用及常用方法解析

    文章来源:https://blog.csdn.net/qwe25878/article/details/85051911#_35 今天,来学习一下Unity新的网络请求方式UnityWebReques ...

  4. Problem B: Bulbs

    Problem B: Bulbs Greg has an m×n grid of Sweet Lightbulbs of Pure Coolness he would like to turn on. ...

  5. 数据结构——KMP(串)

    KMP一个非常经典的字符串模式匹配算法,虽然网上有很多kmp算法的博客,但是为了更好的理解kmp我还是自己写了一遍(这个kmp的字符串存储是基于堆的(heap),和老师说的定长存储略有不同,字符串索引 ...

  6. Postman配置Pre-request scripts预请求对请求进行AES加密

    1.首先,Postman的Pre-request scripts页面右边已经提供了一些模板,这些模板可以设置变量与环境变量,并使用双大括号对变量进行引用 {{info}} 2.对所有POST请求都进行 ...

  7. PYTHON画三维图

    import matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dimport numpy as np #bbb=[1 if ...

  8. Spring课程 Spring入门篇 7-3 advice扩展

    课程链接: 1 解析 1.1 advice中aspect 切面传参 1.2 通知参数名称——argNames属性, 参数为 JoinPoint.ProceedingJoinPoint.JoinPoin ...

  9. FindWindowXG

    测试: 函数代码: function FindWindowXG(strClass, strTitle: string): THandle; var hd: THandle; arrClass: ..] ...

  10. NumPy 基于已有数据创建数组

    原文:Python Numpy 教程 章节 Numpy 介绍 Numpy 安装 NumPy ndarray NumPy 数据类型 NumPy 数组创建 NumPy 基于已有数据创建数组 NumPy 基 ...