1.最近公共祖先:对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、的祖先且x的深度尽可能大。

2.朴素算法:记录下每个节点的父亲,使节点u,v一步一步地向上找父亲,直到找到相同的“祖先”,即是所求的答案,时间复杂度O(n)。

3.优化算法(倍增法):利用二进制的思想,想办法使一步一步向上搜变成以2^k地向上跳所以定义一个P[][]数组,使p[i][j]表示节点i的2^j倍祖先,因此p[i][0]即为i的父亲。我们可以得到一个递推式p[i][j]=p[p[i][j-1]][j-1]。这样子一个O(NlogN)的预处理(dfs)的 2^k 的祖先。定义一个deep[]数组表示节点深度,先判断是否 deep[u] > deep[v]果是的话就交换一下(保证 u的深度小于 v方便下面的操作)然后把u到与v同深度,同深度以后再把u v同时往上调(dec(j)) 调到有一个最小的j 满足: p[u] [j]!=p[v][j],u,v是在不断更新的   最后把u,v 往上调 (u=p[u,0] v=p [v,0]) 一个一个向上调直到   u= v 这时 u or v就是公共祖先。复杂度:O(logn)

下面给出 LCA 的模板:

输入:第一行:N,M,Q     (因为是一棵树,所以M==N-1)

接下来M 行: u, v, c ,表示u到v连一条权值为c的边

接下来Q行:u, v 表示寻求u,v的最近公共祖先,u~v的距离,u~v之间的路径的最大权值

输出:共Q行,对应上述的询问

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<algorithm>
  6. #include<cstring>
  7. #include<vector>
  8. #include<queue>
  9. using namespace std;
  10. const int maxn=;
  11. inline int read(){
  12. int x=,f=;char ch=getchar();
  13. while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
  14. while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
  15. return x*f;
  16. }
  17. int N,M,Q;
  18. vector<int> to[maxn],cost[maxn];
  19. int p[maxn][],MAX[maxn][],sum[maxn][];
  20. int dep[maxn];
  21. inline void dfs(int root){
  22. for(int i=;i<to[root].size();i++){
  23. int y=to[root][i];
  24. if(y!=p[root][]){
  25. dep[y]=dep[root]+;
  26. p[y][]=root;
  27. MAX[y][]=cost[root][i];
  28. sum[y][]=cost[root][i];
  29. for(int k=;k<=30;k++){
  30. int zu=<<k;
  31. if(zu<=dep[y]){
  32. p[y][k]=p[p[y][k-]][k-];
  33. MAX[y][k]=max(MAX[y][k-],MAX[p[y][k-]][k-]);
  34. sum[y][k]=sum[y][k-]+sum[p[y][k-]][k-];
  35. }
  36. }
  37. dfs(y);
  38. }
  39. }
  40. }
  41. inline void LCA(int x,int y){
  42. int ans1=,ans2=;
  43. if(dep[x]>dep[y]) swap(x,y);
  44. int delta=dep[y]-dep[x];
  45. for(int i=;i<=;i++){
  46. int h=<<i; h=h&delta;
  47. if(h!=){
  48. ans1+=sum[y][i]; ans2=max(ans2,MAX[y][i]);
  49. y=p[y][i];
  50. }
  51. }
  52. if(x==y){
  53. cout<<x<<" "<<ans1<<" "<<ans2<<endl;
  54. return ;
  55. }
  56. for(int i=;i>=;i--){
  57. if(p[y][i]!=p[x][i]){
  58. ans1+=sum[x][i]; ans1+=sum[y][i];
  59. ans2=max(ans2,MAX[x][i]); ans2=max(ans2,MAX[y][i]);
  60. x=p[x][i]; y=p[y][i];
  61. }
  62. }
  63. ans1+=sum[x][]; ans1+=sum[y][];
  64. ans2=max(ans2,MAX[x][]); ans2=max(ans2,MAX[y][]);
  65. cout<<p[x][]<<" "<<ans1<<" "<<ans2<<endl;
  66. }
  67. int main(){
  68. N=read(); M=read(); Q=read();
  69. for(int i=;i<=M;i++){
  70. int u,v,c;
  71. u=read(); v=read(); c=read();
  72. to[u].push_back(v); to[v].push_back(u);
  73. cost[u].push_back(c); cost[v].push_back(c);
  74. }
  75. p[][]=-; dep[]=;
  76. dfs();
  77. for(int i=;i<=Q;i++){
  78. int u,v;
  79. u=read(); v=read();
  80. LCA(u,v);
  81. }
  82. return ;
  83. }

用“倍增法”求最近公共祖先(LCA)的更多相关文章

  1. LCA 在线倍增法 求最近公共祖先

    第一步:建树  这个就不说了 第二部:分为两步  分别是深度预处理和祖先DP预处理 DP预处理: int i,j; ;(<<j)<n;j++) ;i<n;++i) ) fa[i ...

  2. 求最近公共祖先(LCA)的各种算法

    水一发题解. 我只是想存一下树剖LCA的代码...... 以洛谷上的这个模板为例:P3379 [模板]最近公共祖先(LCA) 1.朴素LCA 就像做模拟题一样,先dfs找到基本信息:每个节点的父亲.深 ...

  3. 倍增法求lca(最近公共祖先)

    倍增法求lca(最近公共祖先) 基本上每篇博客都会有参考文章,一是弥补不足,二是这本身也是我学习过程中找到的觉得好的资料 思路: 大致上算法的思路是这样发展来的. 想到求两个结点的最小公共祖先,我们可 ...

  4. 最近公共祖先 LCA 倍增算法

          树上倍增求LCA LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 ...

  5. 倍增法求LCA

    倍增法求LCA LCA(Least Common Ancestors)的意思是最近公共祖先,即在一棵树中,找出两节点最近的公共祖先. 倍增法是通过一个数组来实现直接找到一个节点的某个祖先,这样我们就可 ...

  6. 【LCA求最近公共祖先+vector构图】Distance Queries

    Distance Queries 时间限制: 1 Sec  内存限制: 128 MB 题目描述 约翰的奶牛们拒绝跑他的马拉松,因为她们悠闲的生活不能承受他选择的长长的赛道.因此他决心找一条更合理的赛道 ...

  7. 【lhyaaa】最近公共祖先LCA——倍增!!!

    高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...

  8. HDU 2586 倍增法求lca

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  9. 最近公共祖先(LCA)的三种求解方法

    转载来自:https://blog.andrewei.info/2015/10/08/e6-9c-80-e8-bf-91-e5-85-ac-e5-85-b1-e7-a5-96-e5-85-88lca- ...

随机推荐

  1. 4、手把手教React Native实战之flexbox布局(伸缩属性)

    ###伸缩项目的属性 1.order 定义项目的排列顺序,数值越小,排列越靠前,默认值为0,语法为:order:整数值 2.flex-grow 定义伸缩项目的放大比例,默认值为0,即表示如果存在剩余空 ...

  2. (转)使用 python Matplotlib 库绘图

    运行一个简单的程序例子: import matplotlib.pyplot as plt plt.plot([1,2,3]) plt.ylabel('some numbers') plt.show() ...

  3. js 跳转的几种方法收藏

    history.go(-n) 返回上一页(n 为返回前几页) window.location.reload(); 刷新当前页面 history.go(-1);window.locatoin.reloa ...

  4. mysql数据库sql优化——子查询优化

    1.什么是子查询.表关联查询: 子查询:是指在主sql语句中的select或where子句中使用select查询语句:select a.name,(select b.name from b where ...

  5. Hibernate中持久化类与持久化对象

    1.JavaBean类 JavaBean类是实体类,必须一下属性,private修饰的成员属性,public修饰的getter与setter访问方法,public修饰的空参构造器,实现Serializ ...

  6. Faster R-CNN利用新的网络结构来训练

    前言 最近利用Faster R-CNN训练数据,使用ZF模型,效果无法有效提高.就想尝试对ZF的网络结构进行改造,记录下具体操作. 一.更改网络,训练初始化模型 这里为了方便,我们假设更换的网络名为L ...

  7. leetcode 326 Power of Three (python)

    原题: Given an integer, write a function to determine if it is a power of three. Follow up: Could you ...

  8. Vue与React的异同 -生命周期

    vue的生命周期 创建前 beforeCreate 创建   create 挂载前 beforeMount 挂载 mounted 更新前 beforeUpdate 更新 updated 销毁前 bef ...

  9. 1.1_php基础语法

    一,变量与常量: 二,php中的运算符(字符串拼接): 三,php数组. <!DOCTYPE html> <html> <head> <meta charse ...

  10. 相似性分析之Jaccard相似系数

    Jaccard, 又称为Jaccard相似系数(Jaccard similarity coefficient)用于比较有限样本集之间的相似性与差异性.Jaccard系数值越大,样本相似度越高 公式: ...