LCA就是最近公共祖先
一个LCA的模板,代码作用注释写有
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
看完代码,有几个需要注意的地方
1.树根的父亲也就是fa[root][0]=0;
2.为什么求lca的过程是合法的?
首先深度不同的xx和yy肯定是不相同的,我们先把xx和yy的深度统一到小的那个上
那么这时候xx和yy离最近公共祖先的距离就是相同的,所以一起往上跳
而且最后他们不可能跳到一块去,会离公共祖先差1(原因:我们知道一个数n可以有若干个不重复的2自然数次幂构成。。。。)
这就是为什么要返回xx的父亲的原因了