最小公共祖先模板
阿新 • • 發佈:2020-08-29
#include <bits/stdc++.h> using namespace std; int fa[2000005][35];//結點i的第2^j級祖先 int dpt[2000010]; int head[2000010]; int ver[2000010]; int nxt[2000010]; int lg[2000010];//預處理一下log(i)+1 int tot=0; int n,m,s; void refer() { for(int i=1;i<=n;i++) { lg[i]=lg[i-1]+(1<<lg[i-1]==i); } } void dfs(int x,int f) { fa[x][0]=f; //結點的第1級祖先就是他的父節點 dpt[x]=dpt[f]+1; /*記錄結點深度*/ int t=lg[dpt[x]]; for(int i=1;i<=t;i++) { fa[x][i]=fa[fa[x][i-1]][i-1];//x的2^i級祖先=x的2^(i-1)級祖先的2^(i-1)級祖先 } for(int i=head[x];i;i=nxt[i]) { int y=ver[i]; if(y==f) continue; dfs(y,x);//繼續向下 } } int latest_common_ancestors(int x,int y) { if(dpt[x]<dpt[y]) swap(x,y);//將x點設為深度較深的點 while(dpt[x]>dpt[y]) { x=fa[x][lg[dpt[x]-dpt[y]]-1]; } if(x==y) return y;//x跳上來發現就是y,那y就肯定是LCA for(int k=lg[dpt[x]]-1;k>=0;k--) //向上 { if(fa[x][k]!=fa[y][k])//因為我們只跳到公共祖先的下一層所以x,y肯定不相等 ,判定他們的父節點是否相等不相等就繼續往下; { x=fa[x][k],y=fa[y][k]; } } return fa[x][0];//返回的是父節點 } void add(int x,int y) { ver[++tot]=y; nxt[tot]=head[x]; head[x]=tot; } int main() { //// freopen("answer.txt","w",stdout); scanf("%d%d%d",&n,&m,&s); refer();//預處理log2(i)+1; for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(s,s); for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); printf("%d\n",latest_common_ancestors(a,b)); } return 0; }