【模板】最近公共祖先(LCA)(树剖做法)
↑题面也在此
我认为很好的树剖讲解
dfs1(){
预处理 heavy_son[1000001],size[1000001],father[1000001],dep[1000001];
heavy_son[1000001] 为root的重儿子
size[1000001] 为以root为根的子树节点个数
father[1000001] 为root的父亲节点
dep[1000001] 为root的深度值
}
dfs2(){
预处理 top[1000001]
top[1000001] 为root所在链的顶端节点
}
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 using namespace std; 6 int N; 7 int n,m,s; 8 int top[1000001],heavy_son[1000001],size[1000001],last[1000001],father[1000001],dep[1000001]; 9 struct node{ 10 int to,next; 11 }a[1000001]; 12 int add(int add_u,int add_v){ 13 a[++N].to=add_v; 14 a[N].next=last[add_u]; 15 last[add_u]=N; 16 return 0;//要打return 0!!! 17 } 18 int dfs1(int F,int root,int deep){ 19 father[root]=F; 20 dep[root]=deep; 21 size[root]=1; 22 int Maxn=0; 23 for(int i=last[root];i;i=a[i].next){ 24 int To=a[i].to; 25 if(To==F) continue; 26 dfs1(root,To,deep+1); 27 size[root]+=size[To]; 28 if(size[To]>Maxn){ 29 Maxn=size[To]; 30 heavy_son[root]=To; 31 } 32 } 33 return 0; 34 } 35 int dfs2(int F,int root,int Top){ 36 top[root]=Top; 37 if(heavy_son[root]) dfs2(root,heavy_son[root],Top);//重链 38 for(int i=last[root];i;i=a[i].next){ 39 int To=a[i].to; 40 if(To==F||To==heavy_son[root]) continue; 41 dfs2(root,To,To);//每条链都是由轻儿子或根节点为TOP 42 } 43 return 0; 44 } 45 int lca(int root_1,int root_2){ 46 while(top[root_1]!=top[root_2]){//不在同一条链 47 if(dep[top[root_1]]>=dep[top[root_2]]) root_1=father[top[root_1]]; 48 else root_2=father[top[root_2]]; 49 } 50 if(dep[root_1]<=dep[root_2]) return root_1;//浅的点为LCA 51 return root_2; 52 } 53 int main(){ 54 //freopen("P3379_1.in","r",stdin); 55 scanf("%d%d%d",&n,&m,&s); 56 for(int i=1;i<=n-1;i++){ 57 int U,V; 58 scanf("%d%d",&U,&V); 59 add(U,V); 60 add(V,U); 61 } 62 dfs1(s,s,1); 63 dfs2(s,s,s); 64 while(m--){ 65 int U,V; 66 scanf("%d%d",&U,&V); 67 printf("%d\n",lca(U,V)); 68 } 69 return 0; 70 }

浙公网安备 33010602011771号