前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?。。)

倍增求LCA:

father【i】【j】表示节点i往上跳2^j次后的节点

可以转移为

father【i】【j】=father【father【i】【j-1】】【j-1】

(此处注意循环时先循环j,再循环i)

然后dfs求出各个点的深度depth

整体思路:

先比较两个点的深度,如果深度不同,先让深的点往上跳,浅的先不动,等两个点深度一样时,if 相同 直接返回,if 不同 进行下一步;如果不同,两个点一起跳,j从大到小枚举(其实并不大),如果两个点都跳这么多后,得到的点相等,两个点都不动(因为有可能正好是LCA也有可能在LCA上方),知道得到的点不同,就可以跳上来,然后不断跳,两个点都在LCA下面那层,所以再跳1步即可,当father【i】【j】中j=0时即可,就是LCA,返回值结束

感谢Sunshinezff学长的编码纠错帮助

下面是代码:“`

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
vector <int> g[100010];
int father[100010][40]={0};
int depth[100010]={0};
int n,m;
bool visit[10010]={false};
int root; void dfs(int u)
{
int i;
visit[u]=true;
for (i=0;i<g[u].size();i++)
{
int v=g[u][i];
if ( !visit[v] )
{
depth[v]=depth[u]+1;
dfs(v);
}
}
}//深搜出各点的深度,存在depth中 void bz()
{
int i,j;
for (j=1;j<=30;j++)
for (i=1;i<=n;i++)
father[i][j]=father[father[i][j-1]][j-1];
}//倍增,处理father数组,详情参照上述讲解 int LCA(int u,int v)
{
if ( depth[u]<depth[v] )
{
int temp=u;
u=v;
v=temp;
}//保证深度大的点为u,方便操作
int dc=depth[u]-depth[v];
int i;
for (i=0;i<30;i++)//值得注意的是,这里需要从零枚举
{
if ( (1<<i) & dc)//一个判断,模拟一下就会很清晰
u=father[u][i];
}
//上述操作先处理较深的结点,使两点深度一致
if (u==v) return u;//如果深度一样时,两个点相同,直接返回
for (i=29;i>=0;i--)
{
if (father[u][i]!=father[v][i])//跳2^j步不一样,就跳,否则不跳
{
u=father[u][i];
v=father[v][i];
}
}
u=father[u][0];//上述过程做完,两点都在LCA下一层,所以走一步即可
return u;
} int main()
{
int i,j;
scanf("%d",&n);
for (i=0;i<=n;i++)
g[i].clear();
for (i=1;i<n;i++)
{
int a,b;
int root;
scanf("%d%d",&a,&b);
g[a].push_back(b);
father[b][0]=a;
if (father[a][0]==0)
root=a;
}
depth[root]=1;
dfs(root);
bz();
int x,y;
scanf("%d%d",&x,&y);
printf("%d",LCA(x,y));
return 0;
}

“`

树上倍增求LCA(最近公共祖先)的更多相关文章

  1. 求LCA最近公共祖先的在线倍增算法模板_C++

    倍增求 LCA 是在线的,而且比 ST 好写多了,理解起来比 ST 和 Tarjan 都容易,于是就自行脑补吧,代码写得容易看懂 关键理解 f[i][j] 表示 i 号节点的第 2j 个父亲,也就是往 ...

  2. [算法]树上倍增求LCA

    LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...

  3. [学习笔记] 树上倍增求LCA

    倍增这种东西,听起来挺高级,其实功能还没有线段树强大.线段树支持修改.查询,而倍增却不能支持修改,但是代码比线段树简单得多,而且当倍增这种思想被应用到树上时,它的价值就跟坐火箭一样,噌噌噌地往上涨. ...

  4. [luogu3379]最近公共祖先(树上倍增求LCA)

    题意:求最近公共祖先. 解题关键:三种方法,1.st表 2.倍增法 3.tarjan 此次使用倍增模板(最好采用第一种,第二种纯粹是习惯) #include<cstdio> #includ ...

  5. cogs 2450. 距离 树链剖分求LCA最近公共祖先 快速求树上两点距离 详细讲解 带注释!

    2450. 距离 ★★   输入文件:distance.in   输出文件:distance.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] 在一个村子里有N个房子,一 ...

  6. 树上倍增求LCA及例题

    先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...

  7. 树上倍增求LCA详解

    LCA(least common ancestors)最近公共祖先 指的就是对于一棵有根树,若结点z既是x的祖先,也是y的祖先(不要告诉我你不知道什么是祖先),那么z就是结点x和y的最近公共祖先. 定 ...

  8. Codeforces 609E (Kruskal求最小生成树+树上倍增求LCA)

    题面 传送门 题目大意: 给定一个无向连通带权图G,对于每条边(u,v,w)" role="presentation" style="position: rel ...

  9. 求LCA最近公共祖先的在线ST算法_C++

    ST算法是求最近公共祖先的一种 在线 算法,基于RMQ算法,本代码用双链树存树 预处理的时间复杂度是 O(nlog2n)   查询时间是 O(1) 的 另附上离线算法 Tarjan 的链接: http ...

随机推荐

  1. 配置Tomcat使用Redis作为session管理

    1. 在 tomcat/lib 中增加以下jar包 commons-pool2-.jar jedis-.jar tomcat-redis-session-manager-.jar 2. 修改tomca ...

  2. JS 关闭 页面 浏览器 事件

    JS监听关闭浏览器事件关键字: js监听关闭浏览器事件Onunload与OnbeforeunloadOnunload,onbeforeunload都是在刷新或关闭时调用,可以在<script&g ...

  3. NOIP2016提高组解题报告

    NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合

  4. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

  5. java多线程系类:JUC原子类:02之AtomicLog原子类

    概要 AtomicInteger, AtomicLong和AtomicBoolean这3个基本类型的原子类的原理和用法相似.本章以AtomicLong对基本类型的原子类进行介绍.内容包括:Atomic ...

  6. mysql新建用户的方法

    新增 insert into mysql.user(Host,User,Password,ssl_cipher,x509_issuer,x509_subject) values("local ...

  7. [转]Linux后台进程管理利器:supervisor

    FROM : http://www.liaoxuefeng.com/article/0013738926914703df5e93589a14c19807f0e285194fe84000 Linux后台 ...

  8. 路由系统的核心对象——Router

    路由系统的核心对象--Router ASP.NET Core应用中的路由机制实现在RouterMiddleware中间件中,它的目的在于通过路由解析为请求找到一个匹配的处理器,同时将请求携带的数据以路 ...

  9. c8051f320学习,单片机不外乎时钟、IO、串口、USB等外设用法

      时钟 IO(输入.输出,如何配置) IO   数字和模拟资源可以通过25个I/O 引脚(C805 1F3 2 0 ),每个端口引脚都可以被定义为 通用I/O(GPIO)或 0 模拟输入 所有端口I ...

  10. GridView的 OnRowDataBound 事件用法

    <asp:GridView ID="RptUsers" runat="server" AutoGenerateColumns="False&qu ...