【模板】最近公共祖先(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 }

 

posted @ 2020-10-26 21:48  latent_Lin  阅读(121)  评论(0)    收藏  举报