LCA[倍增][树剖][tarjan]

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LCA[倍增][树剖][tarjan]相关的知识,希望对你有一定的参考价值。

LCA:最近公共祖先

倍增:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<vector>
 5 using namespace std;
 6 #define N 105
 7 int deep[N],dad[N][21];
 8 vector<int>vec[N];
 9 int lca(int x,int y) {
10     if(deep[x]>deep[y])swap(x,y);
11     for(int i=20;i>=0;i--)
12         if(deep[dad[y][i]]>=deep[x])y=dad[y][i];
13     if(x==y)return x;
14     for(int i=20;i>=0;i--)
15         if(dad[x][i]!=dad[y][i])x=dad[x][i],y=dad[y][i];
16     return dad[x][0];
17 }
18 void dfs(int x) {
19     deep[x]=deep[dad[x][0]]+1;
20     for(int i=0;dad[x][i];i++)
21         dad[x][i+1]=dad[dad[x][i]][i];
22     for(int i=0;i<vec[x].size();i++)
23         if(!deep[vec[x][i]])dad[vec[x][i]][0]=x,dfs(vec[x][i]);
24 }
25 int main() {
26     int n,Q,u,v,x,y;
27     scanf("%d",&n);
28     for(int i=1;i<n;i++) {
29         scanf("%d%d",&u,&v);
30         vec[u].push_back(v);
31         vec[v].push_back(u);
32     }
33     dfs(1);
34     scanf("%d",&Q);
35     while(Q--) {
36         scanf("%d%d",&x,&y);
37         printf("%d\n",lca(x,y));
38     }
39     return 0;
40 }

树剖:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 #define N 105
 7 int deep[N],top[N],dad[N],size[N];
 8 vector<int>vec[N];
 9 void dfs(int x) {
10     size[x]=1;deep[x]=deep[dad[x]]+1;
11     for(int i=0;i<vec[x].size();i++)
12         if(vec[x][i]!=dad[x]) {
13             dad[vec[x][i]]=x;
14             dfs(vec[x][i]);
15             size[x]+=size[vec[x][i]];
16         }
17 }
18 void dfs1(int x) {
19     int t=0;if(!top[x])top[x]=x;
20     for(int i=0;i<vec[x].size();i++)
21         if(vec[x][i]!=dad[x]&&size[vec[x][i]]>size[t])t=vec[x][i];
22     if(t)top[t]=top[x],dfs1(t);
23     for(int i=0;i<vec[x].size();i++)
24         if(vec[x][i]!=dad[x]&&vec[x][i]!=t)dfs1(vec[x][i]);
25 }
26 int lca(int x,int y) {
27     while(top[x]!=top[y]) {
28         if(deep[top[x]]<deep[top[y]])swap(x,y);
29         x=dad[x];
30     }
31     if(deep[x]>deep[y])swap(x,y);
32     return x;
33 }
34 int main() {
35     int n,u,v,Q,x,y;
36     scanf("%d",&n);
37     for(int i=1;i<n;i++) {
38         scanf("%d%d",&u,&v);
39         vec[u].push_back(v);
40         vec[v].push_back(u);
41     }
42     dfs(1);
43     dfs1(1);
44     scanf("%d",&Q);
45     while(Q--) {
46         scanf("%d%d",&x,&y);
47         printf("%d\n",lca(x,y));
48     }
49     return 0;
50 }

tarjan

 1 #include<cstdio>
 2 #include<vector>
 3 using namespace std;
 4 #define N 1105
 5 int fa[N],qx[N],qy[N],ans[N],dad[N],x,y;
 6 vector<int>vec[N],que[N];
 7 int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
 8 int dfs(int x) {
 9     fa[x]=x;
10     for(int i=0;i<vec[x].size();i++)
11         if(dad[x]!=vec[x][i])
12             dad[vec[x][i]]=x,dfs(vec[x][i]);
13     for(int i=0;i<que[x].size();i++)
14         if(dad[y=qx[que[x][i]]^qy[que[x][i]]^x])
15             ans[que[x][i]]=find(y);
16     fa[x]=dad[x];
17 }
18 int main() {
19     int n,m;
20     scanf("%d%d",&n,&m);
21     for(int i=1;i<n;i++) {
22         scanf("%d%d",&x,&y);
23         vec[x].push_back(y);
24         vec[y].push_back(x);
25     }
26     for(int i=1;i<=m;i++) {
27         scanf("%d%d",&qx[i],&qy[i]);
28         que[qx[i]].push_back(i);
29         que[qy[i]].push_back(i);
30     }
31     dfs(1);
32     for(int i=1;i<=m;i++)
33         printf("%d\n",ans[i]);
34     return 0;
35 }

我会补发注释的

以上是关于LCA[倍增][树剖][tarjan]的主要内容,如果未能解决你的问题,请参考以下文章

51nod2621 树上距离一题四解ST表+倍增+Tarjan+树剖

lca

最近在写一些树上的东西,先发一波LCA的吧!

LCA (Tarjan&倍增)

倍增 Tarjan 求LCA

LCA算法解析-Tarjan&倍增