https://www.cnblogs.com/lbssxz/p/11114819.html
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int maxn=1e5+10; 5 int n,m,s,num=0,head[maxn],dep[maxn],f[maxn][23]; 6 int a1,a2; 7 struct edg{ 8 int next,to; 9 }G[maxn]; 10 void edge_add(int u,int v)//链式前向星存图 11 { 12 num++; 13 G[num].next=head[u];G[num].to=v;head[u]=num; 14 G[++num].next=head[v];G[num].to=u;head[v]=num; 15 } 16 void dfs(int u,int father)//对应深搜预处理f数组 17 { 18 dep[u]=dep[father]+1; 19 for(int i=1;(1<<i)<=dep[u];i++){ 20 f[u][i]=f[f[u][i-1]][i-1]; 21 } 22 for(int i=head[u];i;i=G[i].next){ 23 int v=G[i].to; 24 if(v==father)continue;//双向图需要判断是不是父亲节点 25 f[v][0]=u; 26 dfs(v,u); 27 } 28 } 29 int lca(int x,int y) 30 { 31 if(dep[x]<dep[y]) swap(x,y); 32 for(int i=20;i>=0;i--)//从大到小枚举使x和y到了同一层 33 { 34 if(dep[f[x][i]]>=dep[y]) 35 x=f[x][i]; 36 if(x==y)return x; 37 } 38 for(int i=20;i>=0;i--)//从大到小枚举 39 { 40 if(f[x][i]!=f[y][i])//尽可能接近 41 { 42 x=f[x][i];y=f[y][i]; 43 } 44 } 45 return f[x][0];//随便找一个**输出 46 } 47 int main(){ 48 scanf("%d%d%d",&n,&m,&s); 49 for(int i=1;i<n;i++){ 50 scanf("%d",&a1); 51 scanf("%d",&a2); 52 edge_add(a1,a2);//链式存边 53 } 54 dfs(s,0); 55 for(int i=1;i<=m;i++){ 56 scanf("%d %d",&a1,&a2); 57 printf("%d\n",lca(a1,a2));//求两个节点的LCA 58 } 59 }
来源:https://www.cnblogs.com/pangbi/p/12485561.html