LCA模板

LCA就是最近公共祖先

一个LCA的模板,代码作用注释写有

 1 int f[MAXN][30];//表示i往上跳2^j格所到的位置,后面还可以适当的增加维数去维护一些值
 2 int depth[MAXN];//表示i的深度
 3 void dfs(int st,int father,int depth){//利用dfs求出父亲节点以及i节点的深度 
 4     depth[st]=depth;fa[st][0]=father;
 5     for(int i=linkk[st];i;i=e[i].next){
 6         if(e[i].y!=father) dfs(e[i].y,st,depth+1);
 7     }
 8 }
 9 getanser(){//用倍增得出f数组 
10     for(in i=1;i<=25;i++){
11         for(int j=1;j<=n;j++){
12             f[j][i]=f[f[j][i-1]][i-1];//f[j][i]由i往上跳到f[j-1][i]再往上跳2^(i-1)得到 
13         }
14     }
15 }
16 int gerlca(int xx,int yy){//求xx和yy的lca
17     if(xx==yy) return xx;//如果xx和yy相同那么就返回xx 
18     if(depth[xx]<depth[yy]) swap(xx,yy);//为了统一下面的代码,如果xx的深度小于yy的深度,就交换xx和yy 
19     for(int i=25;i>=0;i--){
20         if(dep[xx]-(2<<i)>=dep[yy]) xx=fa[xx][i];//如果xx的深度往上跳1^i还比yy的深度大并且没有跳出范围的话,就跳 
21     } 
22     //跳完后xx和yy的深度相等 
23     if(xx==yy) return xx;//如果这时候xx和yy相等就返回xx 
24     for(int i=25;i>=0;i--){
25         if(fa[xx][i]!=fa[yy][i]&&fa[xx][i]!=0){//如果不相等并且没有跳出范围的话,xx和yy同时往上跳1^i 
26             xx=fa[xx][i];yy=fa[yy][i];
27         } 
28     }
29     return fa[xx][0];//返回xx的父亲 
30 }
View Code

看完代码,有几个需要注意的地方

1.树根的父亲也就是fa[root][0]=0;

2.为什么求lca的过程是合法的?

首先深度不同的xx和yy肯定是不相同的,我们先把xx和yy的深度统一到小的那个上

那么这时候xx和yy离最近公共祖先的距离就是相同的,所以一起往上跳

而且最后他们不可能跳到一块去,会离公共祖先差1(原因:我们知道一个数n可以有若干个不重复的2自然数次幂构成。。。。)

这就是为什么要返回xx的父亲的原因了

posted @ 2017-11-07 15:21  zhangenming  阅读(338)  评论(0编辑  收藏  举报