最近公共祖先LCA

P3379 【模板】最近公共祖先(LCA) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

倍增LCA

从两个点不断地向上跳,为了避免跳过和准确跳到,弹跳幅度逐渐减小,但要注意先使两个点的深度平齐,如此一块跳才能一块找到最近公共祖先

就如同两个实力相同的rabbits在比赛,为了比赛的公平性,先使距离终点远的rabbit到达同一距离,之后随之一声枪响,一块跳往终点,但rabbits的体力是有限的,因此越跳能跳的距离就越小,因此跳的越来越近(不要忘了远的rabbit到达起点后,要休息一阵,才开始比赛)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int lg=19;
 4 const int N=500005*2;
 5 int n,m,s,cnt;
 6 int f[N][lg+1],deep[N],head[N];
 7 struct node
 8 {
 9     int to,nex;
10 }e[N];
11 void add(int x,int y)
12 {
13     e[++cnt]=(node){y,head[x]};
14     head[x]=cnt;
15 }
16 void dfs(int x)
17 {
18     for(  int i=head[x];i;i=e[i].nex)
19     {
20         int t=e[i].to;
21         if(!deep[t])
22         {
23             deep[t]=deep[x]+1;   
24             f[t][0]=x;
25             dfs(t);
26         }
27     }
28 }
29 int lca(int x,int y)
30 {
31     if(deep[x]<deep[y])swap(x,y); 
32     for(int i=lg;i>=0;--i)
33     {
34         if(deep[f[x][i]]>=deep[y])
35         x=f[x][i];
36     }
37     if(x==y)return y;
38     for(int i=lg;i>=0;--i)
39     {
40         if(f[x][i]!=f[y][i])
41         {
42             x=f[x][i];
43             y=f[y][i];
44         }
45     }    
46     return f[x][0];
47 }
48 int main()
49 {
50     cin>>n>>m>>s;
51     for(int i=1;i<=n-1;++i)
52     {
53         int x,y;
54         cin>>x>>y;
55         add(x,y);
56         add(y,x);
57     }
58     deep[s]=1;
59     dfs(s);
60     for(int j=1;j<=lg;++j)    
61     for(int i=1;i<=n;++i)
62     {
63         f[i][j]=f[f[i][j-1]][j-1];
64     }
65     for(int i=1;i<=m;++i)
66     {
67         int a,b;
68         cin>>a>>b;
69         cout<<lca(a,b)<<endl;
70     }
71     return 0;
72 }

 

posted @ 2021-11-19 17:17  yfmd  阅读(28)  评论(0编辑  收藏  举报