博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LCA (最近公共祖先)倍增做法 —— O(nlogn)预处理 O(logn)(在线)查询
阅读量:5152 次
发布时间:2019-06-13

本文共 1198 字,大约阅读时间需要 3 分钟。

pa[a][j] 表示 a 结点的 2^j倍祖先(j = 0时 为直接父亲,j = 1时为父亲的父亲……)

1.首先预处理出所有结点的深度值dep和父亲结点

1 void dfs(int u, int f, int d) { 2     dep[u] = d; 3     pa[u][0] = f; 4     for(int i = 0; i < G2[u].size(); i++) { 5         edge& e = E[G2[u][i]]; 6         int v = e.u == u ? e.v : e.u; 7         if(v != f) { 8             dfs(v, u, d+1); 9         }10     }11 }

2.预处理出所有结点的 2^j 倍祖先

1 void pre() {2     for(int j = 1; (1<
< n; j++) 3 for(int i = 1; i <= n; i++) if(pa[i][j-1] != -1)4 pa[i][j] = pa[pa[i][j-1]][j-1]; 5 }

3.查询操作,首先将 a,b中深度较大的结点上升到与深度较小的结点同一深度,然后两个结点同步上移,直到上移到最近公共祖先的直接儿子处。

1 int lca(int a, int b)//最近公共祖先 2 { 3     int i, j; 4     if(dep[a] < dep[b]) swap(a, b); 5     for(i = 0; (1<
<= dep[a]; i++); 6 i--; 7 //使a,b两点的深度相同 8 for(j = i; j >= 0; j--) 9 if(dep[a] - (1<
= dep[b])10 a=pa[a][j];11 if(a == b) return a;12 //倍增法,每次向上进深度2^j,找到最近公共祖先的子结点13 for(j = i; j >= 0; j--) {14 if(pa[a][j] != -1 && pa[a][j] != pa[b][j]) {15 a = pa[a][j];16 b = pa[b][j];17 }18 }19 return pa[a][0];20 }

 

转载于:https://www.cnblogs.com/Kiraa/p/6141217.html

你可能感兴趣的文章
gzip
查看>>
转负二进制(个人模版)
查看>>
LintCode-Backpack
查看>>
查询数据库锁
查看>>
我对于脚本程序的理解——百度轻应用有感
查看>>
面试时被问到的问题
查看>>
注解小结
查看>>
list control控件的一些操作
查看>>
判断字符串在字符串中
查看>>
oracle 创建暂时表
查看>>
201421410014蒋佳奇
查看>>
Xcode5和ObjC新特性
查看>>
Centos 7.0 安装Mono 3.4 和 Jexus 5.6
查看>>
CSS属性值currentColor
查看>>
Real-Time Rendering 笔记
查看>>
Activity之间的跳转:
查看>>
实验四2
查看>>
多路复用
查看>>
Python数据可视化之Pygal(雷达图)
查看>>
Java学习笔记--字符串和文件IO
查看>>