方法1:倍增

1498ms

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <cmath>
  6. using namespace std;
  7. typedef long long ll;
  8. const int N=5e5+;
  9. inline int read(){
  10. char c=getchar();int x=,f=;
  11. while(c<''||c>''){if(c=='-')f=-;c=getchar();}
  12. while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
  13. return x*f;
  14. }
  15. int n,q,root,a,b;
  16. struct edge{
  17. int v,ne;
  18. }e[N<<];
  19. int cnt=,h[N];
  20. inline void ins(int u,int v){
  21. cnt++;
  22. e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
  23. cnt++;
  24. e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
  25. }
  26. int fa[N][],deep[N],vis[N];
  27. void dfs(int u){
  28. vis[u]=;
  29. for(int j=;(<<j)<=deep[u];j++)
  30. fa[u][j]=fa[fa[u][j-]][j-];
  31. for(int i=h[u];i;i=e[i].ne){
  32. int v=e[i].v;
  33. if(vis[v]) continue;
  34. deep[v]=deep[u]+;
  35. fa[v][]=u;
  36. dfs(v);
  37. }
  38. }
  39. int lca(int x,int y){
  40. if(deep[x]<deep[y]) swap(x,y);
  41. int bin=deep[x]-deep[y];
  42. for(int i=;i<=;i++)
  43. if((<<i)&bin) x=fa[x][i];//,printf("x %d\n",i);
  44.  
  45. for(int i=;i>=;i--)
  46. if(fa[x][i]!=fa[y][i]){
  47. x=fa[x][i];
  48. y=fa[y][i];
  49. }
  50. if(x==y) return x;
  51. else return fa[x][];
  52. }
  53. int main(int argc, const char * argv[]) {
  54. n=read();q=read();root=read();
  55. for(int i=;i<=n-;i++) a=read(),b=read(),ins(a,b);
  56. dfs(root);
  57. for(int i=;i<=q;i++){
  58. a=read();b=read();
  59. printf("%d\n",lca(a,b));
  60. }
  61. return ;
  62. }

方法2:树链剖分

1314ms

让链首深度大的走到重链的父节点直到在一条重链上,返回深度小的节点

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <cmath>
  6. using namespace std;
  7. typedef long long ll;
  8. const int N=5e5+;
  9. inline int read(){
  10. char c=getchar();int x=,f=;
  11. while(c<''||c>''){if(c=='-')f=-;c=getchar();}
  12. while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
  13. return x*f;
  14. }
  15. int n,q,root,a,b;
  16. struct edge{
  17. int v,ne;
  18. }e[N<<];
  19. int cnt=,h[N];
  20. inline void ins(int u,int v){
  21. cnt++;
  22. e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
  23. cnt++;
  24. e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
  25. }
  26. int fa[N],deep[N],mx[N],size[N];
  27. void dfs(int u){
  28. size[u]++;
  29. for(int i=h[u];i;i=e[i].ne){
  30. int v=e[i].v;
  31. if(v==fa[u]) continue;
  32. fa[v]=u;deep[v]=deep[u]+;
  33. dfs(v);
  34. size[u]+=size[v];
  35. if(size[v]>size[mx[u]]) mx[u]=v;
  36. }
  37. }
  38. int tid[N],top[N],tot;
  39. void dfs(int u,int anc){
  40. if(!u) return;
  41. tid[u]=++tot;top[u]=anc;
  42. dfs(mx[u],anc);
  43. for(int i=h[u];i;i=e[i].ne){
  44. int v=e[i].v;
  45. if(v!=fa[u]&&v!=mx[u]) dfs(v,v);
  46. }
  47. }
  48. int lca(int x,int y){
  49. while(top[x]!=top[y]){
  50. if(deep[top[x]]<deep[top[y]]) swap(x,y);
  51. x=fa[top[x]];
  52. }
  53. if(deep[x]>deep[y]) swap(x,y);
  54. return x;
  55. }
  56. int main(int argc, const char * argv[]) {
  57. n=read();q=read();root=read();
  58. for(int i=;i<=n-;i++) a=read(),b=read(),ins(a,b);
  59. dfs(root);
  60. dfs(root,root);
  61. for(int i=;i<=q;i++){
  62. a=read();b=read();
  63. printf("%d\n",lca(a,b));
  64. }
  65. return ;
  66. }

LCA 倍增||树链剖分的更多相关文章

  1. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  2. 洛谷P4180 [BJWC2010]次小生成树(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  3. 【BZOJ3626】LCA(树链剖分,Link-Cut Tree)

    [BZOJ3626]LCA(树链剖分,Link-Cut Tree) 题面 Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. ...

  4. 培训补坑(day8:树上倍增+树链剖分)

    补坑补坑.. 其实挺不理解孙爷为什么把这两个东西放在一起讲..当时我学这一块数据结构都学了一周左右吧(超虚的) 也许孙爷以为我们是省队集训班... 好吧,虽然如此,我还是会认真写博客(保证初学者不会出 ...

  5. uva 12655 Trucks [LCA](树链剖分+MST)

    The Subtle Balloons Company (SBC) is the main balloon provider for programming contests; it hashuge ...

  6. CF 191C Fools and Roads lca 或者 树链剖分

    They say that Berland has exactly two problems, fools and roads. Besides, Berland has n cities, popu ...

  7. 从lca到树链剖分 bestcoder round#45 1003

    bestcoder round#45 1003 题,给定两个点,要我们求这两个点的树上路径所经过的点的权值是否出现过奇数次.如果是一般人,那么就是用lca求树上路径,然后判断是否出现过奇数次(用异或) ...

  8. P3379 【模板】最近公共祖先(LCA)(树链剖分)版

    #include <bits/stdc++.h> #define read read() #define up(i,l,r) for(register int i = (l);i < ...

  9. 2018.09.16 bzoj3626: [LNOI2014]LCA(树链剖分)

    传送门 树链剖分好题. 对于每个点维护一个值vi" role="presentation" style="position: relative;"&g ...

随机推荐

  1. DDD心得

    使用DDD分层架构有哪些好处 帮你更集中的管理业务逻辑. 帮你降低各层间,以及各业务模块间的依赖关系. 帮你更方便的进行单元测试. 我的DDD分层架构使用经验 使用充血模型,将业务逻辑尽量放到领域实体 ...

  2. php基础知识

    PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言[脚本在服务器上执行]. PHP 文件能够包含文本.HTML.CSS 以及 PHP 代码,在服务器上的执行结果以纯文本返回浏览器. php可以 ...

  3. 3、ASP.NET MVC入门到精通——Entity Framework增删改查

    这里我接上讲Entity Framework入门.从网上下载Northwind数据库,新建一个控制台程序,然后重新添加一个ado.net实体数据模型. EF中操作数据库的"网关"( ...

  4. [原][C#][winForm]分级基金折溢价WinForm网络计算器

    分级基金折溢价WinForm网络计算器 通过子/母基金代码,从 [ 东方财富网,天天基金网,新浪 ] 抓取分级基金的子母基金数据(代码,名称,净值,价格), 并计算出子基金(A基金,B基金)以及母基金 ...

  5. angular源码分析:$compile服务——指令的编写

    这一期中,我不会分析源码,只是翻译一下"https://docs.angularjs.org/api/ng/service/$compile",当然不是逐字逐句翻译,讲解指令应该如 ...

  6. TypeScript的4种编译方式

    1.手动编译 1.1.首先找到TypeScript的安装目录,我的在"C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.0".

  7. javascript的函数

    1.函数的声明 (1) function命令方式 function fn(){}; (2) 函数的表达式 采用变量赋值的方式,function命令后面不带有函数名.如果加上函数名,那么该函数名只在函数 ...

  8. SharePoint 自定义的列表页面中添加javascript的一个 For循环语句后,该页面就打不开了。

    一个sharepoint 2013的普通的列表的自定义新建页面,我在其中新添加几行javascript代码后页面就打不开了.如图所示: 真是一言不合,友谊的页面说打不开就打不开啊.后来慢慢比对发现是因 ...

  9. IOS开发基础知识--碎片38

    1:FCUUID获取设备标识的运用 a:作者 githun地址 https://github.com/fabiocaccamo/FCUUID 因为里面还用到作者的另外一个类UICKeyChainSto ...

  10. 安装gem所需知道的

    1 在中国rubygem源被墙了,所以不管是gem install 还是bundle install都需要修改默认的源,淘宝和ruby-china都提供了源. gem source -r http:/ ...