zoukankan      html  css  js  c++  java
  • 关于LCA的倍增解法的笔记

      emmmmm近日刚刚学习了LCA的倍增做法,写一篇BLOG来加强一下印象w

      首先 何为LCA? 

      LCA“光辉”是印度斯坦航空公司(HAL)为满足印度空军需要研制的单座单发轻型全天候超音速战斗攻击机,主要任务是...

      LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先。

      怎么样,很好理解吧!

      然后,关于倍增

      emmmmm,可以这么理解:

      ……

      ……

      ……

      https://blog.csdn.net/jarjingx/article/details/8180560(太烂啦有空再自己填一下这个坑吧x

      怎么样,很好理解吧!

      (懒癌患者是这样的orz,对不住各位观众老爷&&神犇啦

      那么!

      怎么把他们结合在一起就是我们要研究的问题啦。

      相信大家第一次看到形似“给出一棵树和若干结点,求他们的LCA”这种问题就会想到爆搜吧(单次最坏和平均时间复杂度都是O(n))

      但是显而易见,万恶机智的出题人是不会放我们这么简单的做法过哒

      这时候我们就需要在原来的爆搜上加上倍增优化一下时间复杂度(优化之后是O(nlogn))

      我们给这种神秘地操作叫做 树上倍增

      总而言之就是

      用一个二维数组fa[i][j]来表示从第i个结点向上跳 2 ^ j 个结点所在的点,那么理所当然的fa[i][0]表示的就是i点的父结点啦

      

     1 int lca(int x, int y) {
     2     if (dep[x] > dep[y]) {
     3         swap(x, y);  //交换x点和y点,让x点在y点上♂面(噫
     4     }
     5     for (int i = 20; i >= 0; i--) { 
     6         if (dep[y] - (1 << i) >= dep[x]) {
     7             y = fa[y][i];     //把y点调整到和x点一个高度
     8         }
     9     }
    10     if(x == y) {
    11         return x;   //这里是特判哦,如果调整后x点和y点一样直接返回x就行啦
    12     }
    13     for(int i = 20; i >= 0; i--) {
    14         if(fa[x][i] == fa[y][i]) {
    15             continue;  //如果他们的父亲向上跳2 ^ i个点后是同一个点的话就找到他们的LCA啦
    16         }
    17         else {
    18             x = fa[x][i]; 
    19             y = fa[y][i];  //要雨♂露♂均♂沾,一起向上跳喏
    20         }
    21     }
    22     return fa[x][0]; 返回LCAqwqqq
    23 }

      以上就是倍增LCA的核心算法啦

      然而要知道的是,现在有许多万恶机智的出题人是会卡我们的倍增哒

      所以我们就需要

      优化优化优化!

      因为涉及到图,我们就可以用一种叫派大星链式前向星的东西来优化它(如果你不知道链式前向星可以看看这个

       下面以洛谷的模板题为例,贴一下自己的代码(感谢kkogoro带我“走进LCA”wwww
      
     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<iostream>
     5 using namespace std;
     6 const int Maxv = 500001; 
     7 
     8 int fa[Maxv * 2][21], head[Maxv], dep[Maxv]; 
     9 int cnt, n, m, s;
    10 
    11 struct edges {
    12     int v, next; 
    13 }edge[Maxv * 2];
    14 
    15 void add(int x, int y){
    16     edge[cnt].v = y; 
    17     edge[cnt].next = head[x]; 
    18     head[x] = cnt++;
    19 }
    20 
    21 void dfs(int u, int father){
    22     dep[u] = dep[father] + 1; 
    23     fa[u][0] = father; 
    24     for (int i = 1; (1 << i) <= dep[u]; i++) {
    25         fa[u][i] = fa[fa[u][i - 1]][i - 1]; 
    26     }
    27     for (int i = head[u]; i != -1; i = edge[i].next) {
    28         int v = edge[i].v;
    29         if (v != father) {
    30             dfs(v, u);
    31         }
    32     }
    33 }
    34 
    35 int lca(int x, int y) {
    36     if (dep[x] > dep[y]) {
    37         swap(x, y);
    38     }
    39     for (int i = 20; i >= 0; i--) {
    40         if (dep[y] - (1 << i) >= dep[x]) {
    41             y = fa[y][i]; 
    42         }
    43     }
    44     if(x == y) {
    45         return x; 
    46     }
    47     for(int i = 20; i >= 0; i--) {
    48         if(fa[x][i] == fa[y][i]) {
    49             continue; 
    50         }
    51         else {
    52             x = fa[x][i]; 
    53             y = fa[y][i]; 
    54         }
    55     }
    56     return fa[x][0]; 
    57 }
    58 
    59 int main(){
    60     int a, b; 
    61     memset(head, -1, sizeof(head));
    62     scanf("%d %d %d", &n, &m, &s); 
    63     for (int i = 1; i < n; i++) {
    64         scanf("%d %d", &a, &b);
    65         add(a, b);
    66         add(b, a);
    67     }
    68     dfs(s, 0); 
    69     for(int i = 1; i <= m; i++) {
    70         scanf("%d %d", &a, &b);
    71         printf("%d
    ", lca(a, b));
    72     }
    73     return 0; 
    74 }
      怎么样
      很好理解吧www
  • 相关阅读:
    20100822 动漫店 员工卡缓存出现问题。
    性能报告——使用AOP与DYNAMICProxy的orm性能测试
    性能报告——反射创建对象
    抓虾 老板体会。
    Pixysoft.framework.configuration 性能提升报告
    今天你抛弃了ASP.NET了吗?问题篇
    20100922 项目重构计划
    经过一年时间的沉淀 再次回首 TCP Socket服务器编程
    对Google Me的社会化网络 “The Real Life Social Network” 翻译
    20100718 项目重构计划
  • 原文地址:https://www.cnblogs.com/GldHkkowo/p/8735042.html
Copyright © 2011-2022 走看看