LCA(最近公共祖先)
来源:互联网 发布:nginx配置ip端口访问 编辑:程序博客网 时间:2024/05/17 20:59
定义
对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。另一种理解方式是把T理解为一个无向无环图,而LCA(T,u,v)即u到v的最短路上深度最小的点。现在给定一个根为1的树,求某两个点的最近公共祖先。
思路:
预处理出每个点的深度再一层一层返回一直到找到相同点
deep[1]=1;void dfs(int nw,int d){ deep[nw]=d; for(int i=0;i<G[nw].size();i++){ int to=G[nw][i]; if(!deep[to]){ par[to]=nw; dfs(to,d+1); } }}
再返回
int LCA(int a,int b){ if(deep[a]>deep[b])swap(a,b); while(deep[a]<deep[b])b=par[b]; while(a!=b){ a=par[a]; b=par[b]; }return a;}
复杂度约为O(n)
但是可以使用倍增优化
以par[i][j] 记录第i个点向上返回2^j的节点
因为2^j==2*2^(j-1)
即得到par[i][j]=ar[par[i][j-1]][j-1];
于是每次dfs出每个点的par[i][0]
void dfs(int c){ for(int i=0;i<G[c].size();i++){ int t=G[c][i]; if(!d[t]){ d[t]=d[c]+1; par[t][0]=c; dfs(t); } } }
再利用动态规划计算出par[i][j]
for(int j=1;j<S;j++) for(int i=1;i<=n;i++) par[i][j]=par[par[i][j-1]][j-1];
于是我们可以利用类似快速幂的思想
int up(int a,int s){ for(int i=0;i<S;i++) if(s&(1<<i))a=par[a][i]; return a;}
于是我们就得到了o(log2n)的算法
int LCA(int a,int b){ if(d[a]>d[b])swap(a,b); b=up(b,d[b]-d[a]); if(a!=b){ for(int i=S-1;i>=0;i--) if(par[a][i]!=par[b][i]) a=par[a][i],b=par[b][i]; //找到最近的不同点 a=par[a][0]; //再上一层即为LCA }return a;}
3 0
- 最近公共祖先LCA
- 最近公共祖先(LCA)
- Lca 最近公共祖先
- LCA----最近公共祖先
- LCA (最近公共祖先)
- LCA最近公共祖先
- LCA 最近公共祖先
- 最近公共祖先 LCA
- LCA--最近公共祖先
- LCA(最近公共祖先)
- LCA最近公共祖先
- LCA(最近公共祖先)
- LCA 最近公共祖先
- 最近公共祖先LCA
- LCA 最近公共祖先
- 【LCA】最近公共祖先
- LCA最近公共祖先
- 最近公共祖先--LCA问题
- Java中的内部类和匿名类
- 音视频同步原理及打时间戳
- apt-get install MySQL before C API
- 整理分享下自己平时工作中写的一些类库
- 99%的人都理解错了HTTP中GET与POST的区别
- LCA(最近公共祖先)
- 关于Object-C中的警告 #pragma message、#warnings、#pragma clang
- Thrift使用
- php导出excel 大数据 时候需要注意的问题
- nodejs微信后台验证
- 取得uuid并且放进钥匙串
- Opencv模块学习
- DOM同时设置mouseover与mouseout事件控制元素显示时出现闪烁问题
- redhat系统下网络配置