先展示把代码发过来,今日有空再更新
#pragma GCC optimize(2) #include<bits/stdc++.h> using namespace std; const int N = 1000000; long long bit[N]; int depth[N],f[N][30]; vector<int> G[N]; void init(){ //预先把2的多少次方计算出来 bit[0]=1; for(int i=1;i<=29;i++) bit[i]=bit[i-1]*2; } void dfs(int u,int par){ //u:当前节点 par:u的父亲节点 depth[u]=depth[par]+1; f[u][0]=par; for(int i=1;i<=29;i++) f[u][i]=f[f[u][i-1]][i-1]; //计算u的各次方的祖先 for(int i=0;i<(int)G[u].size();i++){ //继续去遍历该节点的孩子节点 int v=G[u][i]; if(v==par) continue;//因为是用邻接表存的,所以需要跳过父亲节点 dfs(v,u); } } int lca(int a,int b){ if(depth[a]<depth[b]) swap(a,b); //保证深度大的在前,小的在后 int dif=depth[a]-depth[b]; //深度差 for(int i=29;i>=0;i--){ if(bit[i] <= dif){ //在不超出深度差的范围向上爬 a=f[a][i]; //爬到的位置 dif -= bit[i]; //深度差更新 } } //此时a,b已经是相同的深度 if(a==b) return a; //如果a,b节点已经相同,所以a,b所在的节点就是lca for(int i=29;i>=0;i--){ if(bit[i]<=depth[a] && f[a][i]!=f[b][i]){ //bit[i]<=depth[a]:表示不跳出树之外 a=f[a][i];b=f[b][i]; } } return f[a][0];//返回lca的儿子的父亲,也就是lca } int main(){ init(); int n,m,s; scanf("%d %d %d",&n,&m,&s); int u,v; for(int i=1;i<=n-1;i++){ scanf("%d %d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs(s,0); while(m--){ scanf("%d %d",&u,&v); printf("%d\n",lca(u,v)); } return 0; }