P3379 【模板】最近公共祖先(LCA)
走过路过不要错过!!
一文让你秒懂倍增求LCA!!
看完不会不要钱!!
会了也不要!!
1 #include<bits/stdc++.h> 2 #define maxn 500001 3 using namespace std; 4 int log2n,n,m,s; 5 struct node{ 6 int next,to; 7 }e[maxn<<1]; 8 int num,head[maxn],deep[maxn],jump[maxn][23]; 9 //num 边的编号 head[i]以i节点为起点的边(存树时是最后一条边,遍历时从第一条边开始遍历) 10 // deep[i] 节点i的深度 jump[i][j] 当前节点为i,向上跳2^j步可以到达的节点位置 11 void add(int from,int to)//建树 12 { 13 e[++num].next=head[from]; 14 e[num].to=to; 15 head[from]=num; 16 } 17 void dfs(int u)//通过深搜确定每个节点的深度 18 { 19 for(int i=head[u];i;i=e[i].next)//邻接表遍历 20 { 21 int v=e[i].to;//边i以节点u为起点以节点v为终点 22 if(v!=jump[u][0])//如果v不是u的父节点 23 { 24 jump[v][0]=u;//那么v的父节点是u 25 deep[v]=deep[u]+1;//所以v的深度比u的深度大一 26 dfs(v);//继续搜QAQ 27 } 28 } 29 } 30 void bzinit()//预处理出每个节点向上走2^i步可以走到的节点位置 31 { 32 for(int i=1;i<=log2n;i++)//2^log2n==n i<=log2n可以保证跳不出n个节点 33 { 34 for(int j=1;j<=n;j++) 35 { 36 jump[j][i]=jump[jump[j][i-1]][i-1]; 37 //2^i-1+2^i-1==2*2^i-1==2^i 故上式成立 38 } 39 } 40 } 41 int lca(int x,int y)//求最近公共祖先 42 { 43 if(deep[x]<deep[y]) swap(x,y);//保证x的深度永远大于y的深度 44 int t=deep[x]-deep[y];//xy之间的高度差 45 for(int i=0;(1<<i)<=n;i++) 46 //从0开始 因为2^0=1 一步是最小的运动单位(1<<i)<=n保证了跳不出n个节点 47 { 48 if(t&(1<<i))//&运算符 只有1&1==1 其余均为零 49 { 50 x=jump[x][i]; 51 //当高度差在二进制下,该位不为零时跳,保证了可以使两个节点先跳到同一高度差 52 /*任何一个正整数都能被表示为一些2的n次方加起来 53 十进制:16=16 15=8+4+2+1 10=8+2 5=4+1 54 二进制:10000=10000 1111=1000+100+10+1 1010=1000+10 101=100+1 */ 55 } 56 } 57 if(x==y) return x; 58 for(int i=log2n;i>=0;i--) 59 //开始跳时先大步跳,后小步跳,避免错过lca 60 { 61 if(jump[x][i]!=jump[y][i]) 62 //当从xy节点跳2^i步不相等时,证明还未找到lca,不存在错过的情况,可以跳 63 { 64 x=jump[x][i]; 65 y=jump[y][i]; 66 } 67 } 68 return jump[x][0]; 69 //当跳至lca以上时,节点相同,为避免这种情况,跳到lca深度加一的点,然后返回该节点的父节点,即lca; 70 } 71 int main() 72 { 73 int x,y; 74 cin>>n>>m>>s; 75 log2n=log(n)/log(2)+1; 76 for(int i=1;i<n;i++) 77 { 78 scanf("%d%d",&x,&y); 79 add(x,y); 80 add(y,x);//建两边图,可以向下建树向上查找之类的 81 } 82 deep[s]=1; 83 jump[s][0]=0; 84 dfs(s); 85 bzinit(); 86 for(int i=1;i<=m;i++) 87 { 88 scanf("%d%d",&x,&y); 89 printf("%d ",lca(x,y)); 90 } 91 return 0; 92 }
这绝对是我写过有最详细注释的代码qwq
而且十分清晰易懂qwq
夸我!!