洛谷P3379

注意:不能与LCA搞混(打久了就会发现两个还是有很大区别的)

   位运算一定要加括号!

   for循环从0到logn还是从logn到0看当前的状态更适合哪种

   第53行预处理一定要注意!(因为没有下标为-1的数组)

   第34行也要注意如何判断当前是否跳点(不需要麻烦的位运算,因为如果能跳,dep[y]自然就会变,如果不跳,dep[y]又不变,每次与(dep[y]-dep[x])进行比较,不影响dep[x]与dep[y]的值;

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define man 500010
  4. inline int read()
  5. { int x=;bool f=;
  6. char ch=getchar();
  7. while(ch<''||ch>''){f=(ch==);ch=getchar();}
  8. while(ch>=''&&ch<=''){x=(x<<)+(x<<)+(ch^);ch=getchar();}
  9. return f?(~x+):x;
  10. }
  11. int dep[man],f[man][];
  12. int n,m,logn,root;
  13. int head[man<<],num=;
  14. struct edeg
  15. { int next,to;}e[man<<];
  16. inline void add(int from,int to)
  17. { e[++num].next=head[from];
  18. e[num].to=to;
  19. head[from]=num;
  20. }
  21. void dfs(int u,int fa,int depth)
  22. { f[u][]=fa;
  23. dep[u]=depth;
  24. for(int i=head[u];i;i=e[i].next)
  25. { int to=e[i].to;
  26. if(to==fa) continue;
  27. dfs(to,u,depth+);
  28. }
  29. return ;
  30. }
  31. inline int LCA(int x,int y)
  32. { if(dep[x]>dep[y]) swap(x,y);
  33. for(int i=;i<logn;i++)
  34. if(((dep[y]-dep[x])>>i)&) y=f[y][i];
  35. if(x==y) return x;
  36. for(int i=logn;i>=;i--)
  37. { if(f[x][i]!=f[y][i])
  38. { x=f[x][i];y=f[y][i];
  39. }
  40. }
  41. return f[x][];
  42. }
  43. int main()
  44. { n=read(),m=read(),root=read();
  45. logn=(int)(log(n)/log(2.0))+;
  46. for(int i=;i<n;i++)
  47. { int u=read(),v=read();
  48. add(u,v);add(v,u);
  49. }
  50. dfs(root,-,);
  51. for(int j=;j<logn;j++)
  52. for(int i=;i<=n;i++)
  53. if(f[i][j]<) f[i][j+]=-;
  54. else f[i][j+]=f[f[i][j]][j];
  55. for(int i=;i<=m;i++)
  56. { int x=read(),y=read();
  57. printf("%d\n",LCA(x,y));
  58. }
  59. return ;
  60. }

 LCA使用BFS应该会快一点吧。。。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<queue>
  4. #include<cstring>
  5. #include<cmath>
  6. using namespace std;
  7. #define man 500005
  8. int n,m,root;
  9. int head[man<<],num=;
  10. inline int read()
  11. { int x=;bool f=;
  12. char ch=getchar();
  13. while(ch<''||ch>''){f=(ch==);ch=getchar();}
  14. while(ch>=''&&ch<=''){x=(x<<)+(x<<)+(ch^);ch=getchar();}
  15. return f?(~x+):x;
  16. }
  17. struct edge
  18. { int next,to;}e[man<<];
  19. inline void add(int from,int to)
  20. { e[++num].next=head[from];
  21. e[num].to=to;
  22. head[from]=num;
  23. }
  24. int f[man][],dep[man],logn;
  25. bool vis[man];
  26. void bfs(int s,int dept)
  27. { memset(vis,,sizeof(vis));
  28. f[s][]=-;dep[s]=dept;
  29. queue<int>q;
  30. q.push(s);
  31. do
  32. { int u=q.front();q.pop();vis[u]=;
  33. for(int i=head[u];i;i=e[i].next)
  34. { int to=e[i].to;
  35. if(!vis[to])
  36. { f[to][]=u;
  37. dep[to]=dep[u]+;
  38. q.push(to);}
  39. }
  40. }while(q.size());
  41. }
  42. inline int LCA(int x,int y)
  43. { if(dep[x]>dep[y]) swap(x,y);
  44. for(int i=;i<logn;i++)
  45. { if(((dep[y]-dep[x])>>i)&)
  46. y=f[y][i];
  47. }
  48. if(x==y) return x;
  49. for(int i=logn;i>=;i--)
  50. { if(f[x][i]!=f[y][i])
  51. { x=f[x][i];
  52. y=f[y][i];
  53. }
  54. }
  55. return f[x][];
  56. }
  57. int main()
  58. { n=read(),m=read(),root=read();
  59. for(int i=;i<n;i++)
  60. { int x,y;
  61. x=read(),y=read();
  62. add(x,y);add(y,x);
  63. }
  64. bfs(root,);
  65. logn=(int)(log(n)/log(2.0))+;
  66. for(int j=;j<logn;j++)
  67. for(int i=;i<=n;i++)
  68. if(f[i][j]<) f[i][j+]=-;
  69. else f[i][j+]=f[f[i][j]][j];
  70. for(int i=;i<=m;i++)
  71. { int x,y;
  72. x=read(),y=read();
  73. printf("%d\n",LCA(x,y));
  74. }
  75. return ;
  76. }

 

[模板]LCA的更多相关文章

  1. 算法模板——LCA(最近公共祖先)

    实现的功能如下——在一个N个点的无环图中,共有N-1条边,M个访问中每次询问两个点的距离 原理——既然N个点,N-1条边,则说明这是一棵树,而且联通.所以以1为根节点DFS建树,然后通过求两点的LCA ...

  2. [模板]LCA的倍增求法解析

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

  3. 模板 树上求LCA 倍增和树链剖分

    //233 模板 LCA void dfs(int x,int f){ for(int i=0;i<E[x].size();i++){ int v = E[x][i]; if(v==f)cont ...

  4. POJ 1330 Nearest Common Ancestors (最近公共祖先LCA + 详解博客)

    LCA问题的tarjan解法模板 LCA问题 详细 1.二叉搜索树上找两个节点LCA public int query(Node t, Node u, Node v) { int left = u.v ...

  5. HDU 2586(LCA欧拉序和st表)

    什么是欧拉序,可以去这个大佬的博客(https://www.cnblogs.com/stxy-ferryman/p/7741970.html)巨详细 因为欧拉序中的两点之间,就是两点遍历的过程,所以只 ...

  6. 浅谈倍增法求解LCA

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

  7. NOIP2015游记——一次开心又失望的旅行

    啊,一年一度的NOIP终于是结束了 以前的大神都有写自己的感受 然而我居然给忘了!!!! 吓得我赶紧来写一份游记 Day.-INF--出发前一个星期 机智的我选择了停课 就是为了OIER这伟大而又光荣 ...

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

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

  9. LCA倍增算法的错误与模板

    先上我原来的错误的代码 type node=^link; link=record num:int64; next:node; end; var fa:..,..] of int64; dep:..] ...

随机推荐

  1. redis总结问题

    简单回顾了redis,在这过程中 首先得了解redis是什么,redis的运用场景,redis支持哪些数据格式,redis如何操作数据,redis如何实现高可用 redis是什么: Redis 是一个 ...

  2. Kong安装教程(v1.0.2)

    使用的软件 Unbuntu 虚拟机(有自己的服务器更好) PostgreSQL kong kong-dashboard docker spring boot 安装 PostgreSQL kong 需要 ...

  3. 04-体验一下apache组织封装的BeanUtil工具包

    apache 自己为程序员们封装了一个专门用于处理的工具类,其功能有(数据类型会自动转成与JavaBean相关的) map转javabean javabean转map javabean对象复制 获取j ...

  4. Java 基础测试题

    一.选择题 1.下面哪些是合法的变量名? ( DEG  ) A.2variable B. .variable2 C. ._whatavariable D._3_ E.$anothervar F.#my ...

  5. Nginx 安装配置教程

    1.安装 Nginx 的先决条件 依赖库:GCC, PCRE, zlib, OpenSSL . * GCC (Nginx 由 C 语言编写,因此需要在系统上安装一个编译工具) 基本上 Linux 自带 ...

  6. Redis梳理

  7. ios7自定义返回按钮后,右滑返回功能失效解决方法

    -(void)viewWillAppear:(BOOL)animated{     [super viewWillAppear:animated];     //开启ios右滑返回     if ([ ...

  8. spring 之 BeanPostProcessor

    粗略一看, 它有这么多实现: 可见, 它是多么基础 而重要的一个 接口啊! 它提供了两个方法: public interface BeanPostProcessor { Object postProc ...

  9. Python cx_Oracle 安装小记

    因为我的个人网站 restran.net 已经启用,博客园的内容已经不再更新.请访问我的个人网站获取这篇文章的最新内容,Python cx_Oracle 安装小记 SQLAlchemy 是 Pytho ...

  10. C# String 与 StringBuilder

    String 字符串不可变性,每次为字符串进行增删或重写赋值会销毁原来的字符串,重新开辟内存空间,因此是非常消耗资源的 字符串可以看做是 char 数组,因此可以用 foreach 对其进行遍历,或者 ...