1.倍增

找两个点的LCA,先让它们深度相同,然后倍增向上跳跃,跳到使他们的值不相同的最浅层的点,那么此点的上方即是LCA。

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#define in(x) scanf("%d",&x);
using namespace std;
int n,m,rt,d[500007],fa[500007][22];
int heade[1000007],nexte[1000007],cnt=0,to[1000007];
void build_tree(int x,int father)
{int k=log(d[x])/log(2);for(int j=1;j<=19;++j)fa[x][j]=fa[fa[x][j-1]][j-1];for(int i=heade[x];i;i=nexte[i]){int u=to[i];if(u!=father){d[u]=d[x]+1;fa[u][0]=x;build_tree(u,x);}}
}
inline int read()
{int x=0,w=1;char ch=0;while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return x*w;
}
int find_lca(int l,int r)
{if(d[l]>d[r]) swap(l,r);//l=4,r=2int k=log(d[r]-d[l]+1)/log(2);for(int i=0;i<=k+1;++i){if((1<<i)&(d[r]-d[l])) r=fa[r][i];if(d[r]==d[l]) break;}if(l==r) return l;k=log(d[l])/log(2);for(int i=k+1;i>=0;--i){if(fa[l][i]==fa[r][i]) continue;l=fa[l][i];r=fa[r][i];}return fa[l][0];
}
int main()
{n=read();m=read();rt=read();for(int i=1;i<=n-1;++i){int x,y;x=read();y=read();nexte[++cnt]=heade[x];heade[x]=cnt;to[cnt]=y;nexte[++cnt]=heade[y];heade[y]=cnt;to[cnt]=x;}d[rt]=1;fa[rt][0]=0;build_tree(rt,-1);for(int i=1;i<=m;++i){int x,y;x=read();y=read();printf("%d\n",find_lca(x,y));}return 0;
}

2.tarjan算法

离线算法,将所求先储存,然后结合并查集深搜点,如果所求的两个点都vis[]==1那么输出他们的father。

不理解就画一下图模拟一下。

#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,rt;
int to[1000009],head[1000009],nxt[1000009],cnt=0,cnt1=0,ans[500009],fa[500009];
int to1[1000009],head1[1000009],nxt1[1000009],mark[1000009];bool vis[500009];
inline int read()
{int x=0,w=1;char ch=0;while(ch<'0'||ch>'9'){if(ch=='-') w=1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return x*w;
}
int find(int x)
{if(fa[x]==x) return x;else return fa[x]=find(fa[x]);
}
void onion(int a,int b)
{int x=find(a),y=find(b);if(x==y) return ;else fa[x]=y;
}
void find_lca(int x,int fa)
{    for(int i=head[x];i;i=nxt[i])if(to[i]!=fa)find_lca(to[i],x);vis[x]=1;for(int i=head1[x];i;i=nxt1[i])if(vis[to1[i]]==1)ans[mark[i]]=find(to1[i]);if(fa!=-1) onion(x,fa);
}
int main()
{n=read();m=read();rt=read();for(int i=1;i<=n;++i)fa[i]=i;for(int i=1;i<=n-1;++i){int x,y;x=read();y=read();nxt[++cnt]=head[x];head[x]=cnt;to[cnt]=y;nxt[++cnt]=head[y];head[y]=cnt;to[cnt]=x;}for(int i=1;i<=m;++i){int x,y;x=read();y=read();nxt1[++cnt1]=head1[x];head1[x]=cnt1;to1[cnt1]=y;mark[cnt1]=i;nxt1[++cnt1]=head1[y];head1[y]=cnt1;to1[cnt1]=x;mark[cnt1]=i;}find_lca(rt,-1);for(int i=1;i<=m;++i)printf("%d\n",ans[i]);return 0;
}

c++最近公共祖先LCA(倍增算法和tarjan)相关推荐

  1. 最近公共祖先 (LCA倍增)

    题目描述: 题目 解题思路: 首先思考暴力算法,我们先将待处理的 u,vu,vu,v 两点移动到相同深度的地方,然后两个一起向个自的父节点往上跳,直到跳到第一次父节点相同的时候这个相同的父节点即为它们 ...

  2. 最近公共祖先(LCA)/倍增LCA

    目录 题目描述: 分析: 链式前向星: 预处理lg数组: DFS求解深度depth和fa数组: LCA: 完整代码: 样例: 题目描述: 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. ...

  3. POJ 1470 Closest Common Ancestors (最近公共祖先LCA 的离线算法Tarjan)

    Tarjan算法的详细介绍,请戳: http://www.cnblogs.com/chenxiwenruo/p/3529533.html #include <iostream> #incl ...

  4. 模板 - LCA最近公共祖先(倍增法、Tarjan、树上差分、LCA优化的次小生成树)

    整理的算法模板合集: ACM模板 注意x和y的LCA可以是x或者y本身 一.LCA的在线倍增算法 /*给定一棵包含 n个节点的有根无向树,有 m个询问,每个询问 给出了一对节点的编号 x和 y,询问 ...

  5. [模板]洛谷T3379 最近公共祖先(LCA) 倍增+邻接表

    一年前听说的这东西...现在终于会了... 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> ...

  6. 树上倍增法求最近公共祖先LCA

    LCA,最近公共祖先,这个东西有很多作用,因此,如何高效求出LCA就成了一个热点的讨论话题. 下面所有的讨论都以图中这棵树为例子. 先来了解下什么是倍增吧,倍增其实就是二分的逆向,二分是逐渐缩小范围, ...

  7. 【C++】最近公共祖先 LCA

    最近公共祖先 百科名片 简单引入 LCA的算法 暴力枚举法 Tarjan离线算法 倍增算法 例题: 题目描述 输入描述 输出描述 样例输入 样例输出 代码 百科名片 最近公共祖先 Lowest Com ...

  8. 图论--最近公共祖先LCA

    最近公共祖先LCA LCA(Least Common Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点u和v最近的公共祖先(另一种说法,离树根最远的公共祖先) 最近公 ...

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

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

最新文章

  1. linux sed命令 常用方法
  2. mysql 统计做饼状图_PHP+mysql+Highcharts实现饼状统计图
  3. storm在运行过程中会自动调整拓扑吗_干粉灭火器灌装机的操作你知道吗?
  4. 几种任务调度的 Java 实现方法与比较--转载
  5. 咖啡馆的故事:FTP, RMI , XML-RPC, SOAP, REST一网打尽
  6. 科技论文的几种类型-如何写好科技论文之我见(二)
  7. opencv进阶学习笔记10:图像金字塔和图像梯度
  8. wxWidgets:wxContextMenuEvent类用法
  9. 使用 ssh 命令来访问(登录/连接)远程服务器主机
  10. Python基础(三)--序列
  11. 2017.9.30 物流运输 思考记录
  12. Jenkins创建新任务
  13. python生成词云_词云制作没那么难,Python 10 行代码就实现了!
  14. flowable实现多实例节点的自由跳转
  15. java 生成er图标_设计数据库 ER 图太麻烦?不妨试试这两款工具,自动生成数据库 ER 图!!!...
  16. 「纯正干货」教你一招解决PDF去密码
  17. mapbox创建空白底图
  18. Fiverr 攻略:跨境自由职业通过 Fiverr 盈利
  19. 猿如意|初识CSDN的开发者工具合集
  20. 怎么判断一篇微信公众号文章阅读量是不是刷上来的?

热门文章

  1. Unity最新版打包AssetBundle和加载的方法
  2. 大数据HBase_04_01
  3. JS验证身份证号码合法性
  4. LINUX:拷贝文件src/指定目录下,文件夹图标上有个叉.更改文件权限可解决该问题。
  5. 专访阿里巴巴量子实验室:最强量子电路模拟器“太章”到底强在哪? 1
  6. Node.js git命令
  7. 【zzuli期中考试】字母倒序
  8. video的基本使用
  9. Android模拟器实现windows虚拟串口通信调试
  10. ubutu16.04台式机没有声音处理方法