lca 倍增模板

混江龙づ霸主 提交于 2020-03-13 12:29:13

https://www.cnblogs.com/lbssxz/p/11114819.html

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 const int maxn=1e5+10;
 5 int n,m,s,num=0,head[maxn],dep[maxn],f[maxn][23];
 6 int a1,a2;
 7 struct edg{
 8     int next,to;
 9 }G[maxn];
10 void edge_add(int u,int v)//链式前向星存图 
11 {
12     num++;
13     G[num].next=head[u];G[num].to=v;head[u]=num;
14     G[++num].next=head[v];G[num].to=u;head[v]=num;
15 }
16 void dfs(int u,int father)//对应深搜预处理f数组 
17 {
18     dep[u]=dep[father]+1;
19     for(int i=1;(1<<i)<=dep[u];i++){
20         f[u][i]=f[f[u][i-1]][i-1];
21     }
22     for(int i=head[u];i;i=G[i].next){
23         int v=G[i].to;
24         if(v==father)continue;//双向图需要判断是不是父亲节点 
25         f[v][0]=u;
26         dfs(v,u);
27     }
28 }
29 int lca(int x,int y)
30 {
31     if(dep[x]<dep[y]) swap(x,y);
32     for(int i=20;i>=0;i--)//从大到小枚举使x和y到了同一层 
33     {
34         if(dep[f[x][i]]>=dep[y])
35             x=f[x][i];
36         if(x==y)return x;
37     }
38     for(int i=20;i>=0;i--)//从大到小枚举 
39     {
40         if(f[x][i]!=f[y][i])//尽可能接近 
41         {
42             x=f[x][i];y=f[y][i];
43         } 
44     } 
45     return f[x][0];//随便找一个**输出 
46 }
47 int main(){
48     scanf("%d%d%d",&n,&m,&s);
49     for(int i=1;i<n;i++){
50         scanf("%d",&a1);
51         scanf("%d",&a2);
52         edge_add(a1,a2);//链式存边 
53     }
54     dfs(s,0);
55     for(int i=1;i<=m;i++){
56         scanf("%d %d",&a1,&a2);
57         printf("%d\n",lca(a1,a2));//求两个节点的LCA 
58     }
59 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!