【模板】最近公共祖先(LCA)
阿新 • • 發佈:2020-08-17
Description
給你一棵有根樹,1為根節點,要求你計算出指定兩個結點的最近公共祖先。
Input
輸入檔案的第一行兩個整數n和m,n為結點個數(2<=n,m<=100,000),結點編號為1到n,m表示詢問次數。
接下來n-1行,每行兩個整數x,y,表示x和y之間有一條邊相連;
接下來m行,每行兩個整數a和b,要求計算出結點a和b的最近公共祖先。
Output
輸出檔案共m行,每行為一個詢問的最近公共祖先的編號。
Sample Input
5 2
1 2
2 3
2 4
5 4
2 5
3 5
Sample Output
2
2
思路
- 樹上倍增求LCA模板
程式碼
#include <iostream> #include <cstdio> #include <cmath> #define maxn 100005 using namespace std; int n,m,cnt,head[maxn],fa[maxn][17],deep[maxn]; struct node{int next,to;}e[maxn<<1]; void addedge(int x,int y){e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;} void dfs(int u,int pre) { fa[u][0]=pre; deep[u]=deep[pre]+1; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v!=pre) dfs(v,u); } } void st() { for(int i=1;i<=log2(n);++i) for(int j=1;j<=n;++j) fa[j][i]=fa[fa[j][i-1]][i-1]; } int lca(int u,int v) { if(deep[u]<deep[v]) swap(u,v); while(deep[u]>deep[v]) u=fa[u][(int)log2(deep[u]-deep[v])]; if(u==v) return u; for(int i=log2(n);i>=0;--i) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i]; return fa[u][0]; } int main() { scanf("%d%d",&n,&m); for(int i=1,u,v;i<n;++i) scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u); dfs(1,0); st(); while(m--) { int u,v; scanf("%d%d",&u,&v); printf("%d\n",lca(u,v)); } return 0; }