最近公共祖先(LCA):倍增
来源:互联网 发布:青岛太阳软件 编辑:程序博客网 时间:2024/06/11 03:11
,https://www.luogu.org/problem/show?pid=3379
最近公共祖先方法有很多的,现在我们利用倍增表求lca
何为倍增表,简单的说是成倍增加表
bz[i][j]表示在第i位上向前推进2^j步
对于一颗有根树,bz[i][j]表示从第i为向根节点走2^j步,就是说高度增加2^j
倍增表功能强大,这里不展开(我不会…)
首先我们讲一下倍增
它的地推公示bz[i][j]=bz[bz[i][j-1]][j-1]
和st表很像的
对于一棵树,我们可以dfs求出bz[i][0]
就是i节点的父节点2^0=1;
然后
for(int j=1;n>=(1<<j);j++) for(int i=1;i<=n;i++) if(bz[i][j-1]) bz[i][j]=bz[bz[i][j-1]][j-1];
在爆搜的同时,我们直接求出deep[i],即深度
然后每读入两个数x,y(deep[y]>=deep[x]),如果他们有高度差,先把较深的点顺着根节点向上爬,爬到两个点相同高度;
首先我们搞一个j=0;不断增加j,使deep[bz[y][j]]>deep[x]
那么deep[bz[y][j-1]]一定小于deep[x]且距离deep[x]较近
显然因为y和bz[y][j-1]都在x的下面所以他们公共最近祖先是一样的
那我们把y提升到bz[y][j-1]的位置
继续重复,直到deep[x]==deep[y];
当然咯j不断增加,有可能bz[y][j]比根节点还大,但这时deep[bz[y][j]]是0,所以不会对答案有影响;
提升到同一高度后,我们就可以同时提升xy,方法和上面一样
直到x==y当然,每个节点本身也是自己的祖先
#include<iostream>#include<cstdlib>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#define LL long longusing namespace std;struct cs{ int to,next;}a[2000004];int head[600005],deep[600005],bz[600001][25];int p,n,m,x,y,z,ll;void inc(int x,int y){ ll++; a[ll].to=y; a[ll].next=head[x]; head[x]=ll;}void dfs(int x,int y,int z){ bz[x][0]=y; deep[x]=z; int k=head[x]; while(k){ if(a[k].to!=y) dfs(a[k].to,x,z+1); k=a[k].next; }}int upone(int stdd,int x){//把两个点提升到相同高度 while(deep[x]!=stdd){ int j=0; while(deep[bz[x][j]]>=stdd)j++; x=bz[x][j-1]; } return x;}int happytogether(int x,int y){//两个点一起提升,只现在更新x点,从y点过来 if(x==y)return x; while(1){ int j=0; if(bz[x][j]==bz[y][j])return bz[x][j]; while(bz[x][j]!=bz[y][j])j++; j--; x=bz[x][j]; y=bz[y][j]; }}int lca(int x,int y){ if(deep[x]>deep[y])swap(x,y); y=upone(deep[x],y); return(happytogether(x,y));}int main(){ scanf("%d%d%d",&n,&m,&p); for(int i=1;i<=n-1;i++){ scanf("%d%d",&x,&y); inc(x,y); inc(y,x); } dfs(p,-6,1); for(int j=1;n>=(1<<j);j++) for(int i=1;i<=n;i++) if(bz[i][j-1]) bz[i][j]=bz[bz[i][j-1]][j-1]; while(m--){ scanf("%d%d",&x,&y); printf("%d\n",lca(x,y)); }}
1 0
- 最近公共祖先(LCA)---倍增法
- 最近公共祖先(LCA):倍增
- 【讲解+模板】最近公共祖先(LCA)(倍增)
- LCA最近公共祖先(朴素+倍增法)
- 最近公共祖先(LCA):tarjan与倍增
- 树上倍增求LCA(最近公共祖先)
- lca(最近公共祖先)倍增模板【pascal】
- LCA(最近公共祖先)倍增法模板及总结
- lca最近公共祖先(st表/倍增)
- LCA(最近公共祖先)倍增法实现
- 倍增法求最近公共祖先(LCA)
- 最近公共祖先(LCA)及其倍增算法实现
- 洛谷 3379 最近公共祖先(LCA 倍增)
- 最近公共祖先(LCA)之树上倍增法
- c++最近公共祖先LCA(倍增算法和tarjan)
- 倍增LCA(最近公共祖先)算法详解
- luogu3379 最近公共祖先(LCA) tarjan 倍增
- 最近公共祖先LCA(Tarjan与DFS--ST倍增)
- 限制log打印速率
- 2017-1-22
- PAT---B1031. 查验身份证(15)
- ThinkPHP 实现Mysql数据库备份
- 远程实习第三周总结
- 最近公共祖先(LCA):倍增
- IBM LDAP ITDS的重置密码操作命令(v6.0版本)
- jquery的Ajax技术和PHP通信
- 算法训练 区间K大数
- RadAsm + OD 搭配编写和调试汇编程序
- 第七章 构造函数&this&静态&单例模式
- iOS程序中的内存分配 栈区堆区全局区
- scanf()输入数字和字符
- python 4-6 如何去掉字符串中不需要的字符strip('-+*')/lstrip()/rstrip()/切片分段+/replace/sub/translate