倍增法求最近公共祖先 笔记与思路整理

一个鶸的第二篇笔记与思路。应该还算比较简要,照常免责。

 

核心为二维father数组:father[i][j]存储第i个点向上跳2^j次到达的点

      如father[i][0]表示点i的父亲,

             [i][1]表示i向上两层,

             [i][2]表示i向上四层。

用一次DFS维护father数组以及dep等等。

详解见函数主体:

int LCA(int x, int y){
    if(dep[x] < dep[y])swap(x,y);  //保证x深于y
    int t = dep[x] - dep[y];  //t为x跳到y同一深度所需步数
    for(int i = 0 ; i <= 20 ; i++)
        if( (1<<i) & t) x = father[x][i];  
      //1左移i次按位与t可得出t在二进制下第i位上是否为1
      //若为1则将x向上跳2^i位,整个循环后正好跳了t位
        
    if(x == y)return x;//是否y为x祖先,即跳到同一高度时已经相等
    
    for(int i = 20 ; i >= 0 ; i--){  //x和y同时向上跳
        if(father[x][i] == father[y][i])continue;  
              //若x和y跳2^i位后已经相等,则跳多了至少一位,不跳这一步
        x = father[x][i]; y = father[y][i];
              //x和y向上跳2^i位后尚未相等,则跳2^i位
    }  //跳完后x与y应该处于“刚好没相等”的层数,即在其最近公共祖先下一层
    
    return father[x][0];  //返回其父亲即为最近公共祖先
}

 

posted @ 2019-08-16 09:45  mzWyt  阅读(216)  评论(0编辑  收藏  举报