n个节点,m个询问,root为根节点,fa[i][j]表示i的第2j个祖先
#include<bits/stdc++.h> using namespace std; const int P=30; //vector son[500001]; //若清楚每条边哪个是父节点那个是子节点,可以用vector,son[i]表示以i为父节点的子节点; int n,m,deep[500001],fa[500001][30]={0},root,jump[500005],num=0; bool judge[500005]={0}; struct nob{ int sta,ed,jump; }a[1000005]; //邻接表存储边 void add(int sta,int ed){ num++; a[num].sta=sta; a[num].ed=ed; a[num].jump=jump[sta]; jump[sta]=num; } void dfs(int pos){ judge[pos]=1; for (int i=jump[pos]; i>0; i=a[i].jump){ if (judge[a[i].ed]) continue; deep[a[i].ed]=deep[pos]+1; fa[a[i].ed][0]=pos; dfs(a[i].ed); } } void beizeng(){ for (int i=1; i<P; i++){ for (int l=1; l<=n; l++){ fa[l][i]=fa[fa[l][i-1]][i-1]; } } } int LCA(int x,int y){ if (deep[y]>deep[x]) swap(x,y); int s=deep[x]-deep[y]; for (int i=0; i<P; i++) if ((1<<i)&s) x=fa[x][i]; //将深度转为二进制,用倍增来跳 if (x==y) return x; for (int i=P-1; i>=0; i--){ if (fa[x][i]!=fa[y][i]){ x=fa[x][i]; y=fa[y][i]; } } return fa[x][0]; } int main(){ scanf("%d%d%d",&n,&m,&root); //若没有说明根节点的话,那么fa[i][0]==0的为根节点 for (int i=1,x,y; i<n; i++){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } deep[root]=1; dfs(root); beizeng(); for (int i=1,x,y; i<=m; i++){ scanf("%d%d",&x,&y); printf("%d ",LCA(x,y)); } return 0; }