传送门

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. #define re register
  7. using namespace std ;
  8. const int maxn = 5 * 1e5 + 4 ;
  9. inline int read () {
  10. int f = 1 , x = 0 ;
  11. char ch = getchar () ;
  12. while (ch > '9' || ch < '0') {if(ch == '-') f = -1 ; ch = getchar () ;}
  13. while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0' ; ch = getchar () ;}
  14. return x * f ;
  15. }
  16. int n , m , s , x , y , a , b , c , d ;
  17. int head[maxn] , tot ;
  18. struct Edge {
  19. int from , to , next ;
  20. }edge[maxn << 1] ;
  21. inline void add (int u , int v) {
  22. edge[++tot].from = u ;
  23. edge[tot].to = v ;
  24. edge[tot].next = head[u] ;
  25. head[u] = tot ;
  26. }
  27. int dep[maxn] , f[maxn][21] ;
  28. /*
  29. dep数组用来记录当前点的深度
  30. f[i][j]代表距离i 2^j的祖先
  31. */
  32. inline void dfs (int x , int fa) {
  33. dep[x] = dep[fa] + 1 ;//更新深度
  34. f[x][0] = fa ;//更新父亲结点
  35. for(re int i = 1 ; (1 << i) <= dep[x] ; ++ i)
  36. //预处理出f数组
  37. f[x][i] = f[f[x][i - 1]][i - 1] ;
  38. //x的2^i级祖先 就是 x的2^(i-1)级祖先的2^(i-1)级祖先。
  39. for(re int i = head[x] ; i ; i = edge[i].next) {
  40. int v = edge[i].to ;
  41. if(v != fa) dfs(v , x) ;
  42. //如果v是x的父亲,那么就说明这条边被访问过了,不能再回溯了
  43. }
  44. }
  45. inline int lca (int a , int b) {
  46. if(dep[a] < dep[b]) swap(a , b) ;//让a的深度更深
  47. for(re int i = 18 ; i >= 0 ; -- i) { //让a跳到跟b相同高度上
  48. if((1 << i) <= (dep[a] - dep[b])) {
  49. a = f[a][i] ;
  50. }
  51. }
  52. if(a == b) return a ; //a,b在同一枝上时,此时a,b会在同一位置,返回任意一个
  53. for(re int i = 18 ; i >= 0 ; -- i) { //从大到小跳
  54. if((1 << i) <= dep[a] && (f[a][i] != f[b][i])) {
  55. //如果不相等,就说明该节点的深度还是比LCA大
  56. a = f[a][i] ;
  57. b = f[b][i] ;
  58. //继续跳
  59. }
  60. }
  61. return f[a][0] ;
  62. //此时a和b不是同一个节点,但是a和b的父亲就是a和b的lca。
  63. }
  64. int main () {
  65. n = read () ; m = read () ; s = read () ;
  66. for(re int i = 1 ; i <= n - 1 ; ++ i) {
  67. x = read () ; y = read () ;
  68. add(x , y) ;
  69. add(y , x) ;
  70. }
  71. dfs(s , 0) ;
  72. while(m--) {
  73. a = read () ; b = read () ;
  74. printf("%d\n" , lca(a , b)) ;
  75. }
  76. return 0 ;
  77. }

洛谷P3379倍增LCA的更多相关文章

  1. 【倍增】洛谷P3379 倍增求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  2. 洛谷P3379 【模板】最近公共祖先(LCA)——LCA

    给一手链接 https://www.luogu.com.cn/problem/P3379 算是lca的模板吧 #include<cstdio> #include<cstring> ...

  3. 洛谷P3379 【模板】最近公共祖先(LCA)(dfs序+倍增)

    P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询 ...

  4. 倍增求LCA学习笔记(洛谷 P3379 【模板】最近公共祖先(LCA))

    倍增求\(LCA\) 倍增基础 从字面意思理解,倍增就是"成倍增长". 一般地,此处的增长并非线性地翻倍,而是在预处理时处理长度为\(2^n(n\in \mathbb{N}^+)\ ...

  5. 【洛谷 p3379】模板-最近公共祖先(图论--倍增算法求LCA)

    题目:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 解法:倍增. 1 #include<cstdio> 2 #include<cstdlib> 3 #include ...

  6. 洛谷P3379 【模板】最近公共祖先(LCA)

    P3379 [模板]最近公共祖先(LCA) 152通过 532提交 题目提供者HansBug 标签 难度普及+/提高 提交  讨论  题解 最新讨论 为什么还是超时.... 倍增怎么70!!题解好像有 ...

  7. 洛谷——P3379 【模板】最近公共祖先(LCA)

    P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询 ...

  8. 【树链剖分】洛谷P3379 树链剖分求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  9. 洛谷 P3379 【模板】最近公共祖先(LCA)

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

随机推荐

  1. 微信 小程序组件 加入购物车全套 one wxml

    <!--pages/shop/shop.wxml--> <view wx:if="{{hasList}}"> <view class="co ...

  2. Pandas笔记目录

    速查笔记 使用实例 Pandas-数据导入 (未完成) Pandas-数据探索 基础属性 shape indexs columns values dtype/dtypes 汇总和计算描述统计 coun ...

  3. code review & github

    code review & github code review https://github.com/features/code-review/ https://github.com/mar ...

  4. nestd事务如果报错了 则回滚到外部事物保存点 且外部事物如果没异常的话 会正常提交 nested事务并不会提交;如果外部事物报错了 内部事务会一同回滚

    nestd事务如果报错了 则回滚到外部事物保存点 且外部事物如果没异常的话 会正常提交 nested事务并不会提交:如果外部事物报错了 内部事务会一同回滚

  5. 从web启动winform程序

    最近有个客户提出想从网站上启动一个客户端的程序,研究了下,实现方法如下: 1. 注入注册表 try                {                    string appPath ...

  6. WEB下载显示下载名称乱码--java

    将文件名编码转换为ISO8859-1即可,如下 downloadFileName = new String(fileName.getBytes("gbk"), "ISO8 ...

  7. 进程和线程(4)-进程 vs. 线程

    进程 vs. 线程 我们介绍了多进程和多线程,这是实现多任务最常用的两种方式.现在,我们来讨论一下这两种方式的优缺点. 首先,要实现多任务,通常我们会设计Master-Worker模式,Master负 ...

  8. 界面编程之QT绘图和绘图设备20180728

    /*******************************************************************************************/ 一.绘图 整 ...

  9. Json对象和Json字符串的区别

    说白了,字符串都是带引号的. 尤其是在使用springmvc的时候,后台@RequestBody接受的是一个json格式的字符串,一定是一个字符串.  参考这个博客还可以: https://blog. ...

  10. webpack全局引入库

    我们在日常开发的时候会遇到一些每个页面都可能会引用到的库(例如jquery) 这可能会导致我们在每一个页面都需要写这样一个语句: import $ from 'jquery'; 可能有人会担心,最后打 ...