LCA(最近公共祖先)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LCA(最近公共祖先)相关的知识,希望对你有一定的参考价值。
三种方法:
1.树链剖分(在上一篇代码中已经讲解得很详细,不再一一赘述)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<climits> #include<ctime> #include<queue> #include<vector> #include<map> #include<algorithm> #include<iomanip> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;i++) #define dep(i,a,b) for(int i=a;i>=b;i--) typedef long long LL; inline int read(){ int x=0;char ch=getchar(); while(ch<‘0‘||ch>‘9‘)ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘){ x=x*10+ch-‘0‘; ch=getchar(); } return x; } const int M=500001; int n,m,root,cnt=0,head[M],to[M<<1],next[M<<1],son[M],siz[M],top[M],dep[M],fa[M]; void Insert(int u,int v){ to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++; to[cnt]=u; next[cnt]=head[v]; head[v]=cnt++; } void dfs1(int u){ siz[u]=1; for(int i=head[u];i!=-1;i=next[i]){ int v=to[i]; if(v!=fa[u]){ fa[v]=u; dep[v]=dep[u]+1; dfs1(v); siz[u]+=siz[v]; if(!son[u]||siz[son[u]]<siz[v])son[u]=v; } } } void dfs2(int u){ if(son[u]){ top[son[u]]=top[u]; dfs2(son[u]); } for(int i=head[u];i!=-1;i=next[i]){ int v=to[i]; if(v!=fa[u]&&v!=son[u]){ top[v]=v; dfs2(v); } } } int lca(int x,int y){ while(1){ int tx=top[x],ty=top[y]; if(tx==ty)return (dep[x]<dep[y]?x:y); if(dep[tx]<dep[ty])y=fa[ty];else x=fa[tx]; } } int main(){ n=read();m=read();root=read(); memset(head,-1,sizeof(head)); rep(i,1,n-1){ int x=read(),y=read(); Insert(x,y); } dep[root]=1; dfs1(root); top[root]=root; dfs2(root); while(m--){ int x=read(),y=read(); printf("%d\\n",lca(x,y)); } return 0; }
2.Tarjan(慎用!如果题目是按照树剖卡常数的话,则此算法会MLE(空间大小为树剖的两倍))
有个特别形象的讲解在这里:http://www.cnblogs.com/JVxie/p/4854719.html
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<vector> #include<map> #include<algorithm> #include<climits> #include<ctime> #include<iomanip> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;i++) #define dep(i,a,b) for(int i=a;i>=b;i--) inline int read(){ int x=0;char ch=getchar(); while(ch<‘0‘||ch>‘9‘)ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘){ x=x*10+ch-‘0‘; ch=getchar(); } return x; } const int M=500001; int n,m,root; bool vis[M]={0}; int cnt=0,tot=0,f[M],ans[M],to[M<<1],head[M],next[M],q[M<<1],nt[M<<1],h[M]; void insert_edge(int x,int y){ to[cnt]=y; next[cnt]=head[x]; head[x]=cnt++; to[cnt]=x; next[cnt]=head[y]; head[y]=cnt++; } void insert_query(int x,int y){ q[tot]=y; nt[tot]=h[x]; h[x]=tot++; q[tot]=x; nt[tot]=h[y]; h[y]=tot++; } int Find(int x){ if(f[x]==x)return x; else return f[x]=Find(f[x]); } void dfs(int fa,int u){ for(int i=head[u];i!=-1;i=next[i]){ int v=to[i]; if(v!=fa)dfs(u,v); } for(int i=h[u];i!=-1;i=nt[i]){ int v=q[i]; if(vis[v])ans[i/2+1]=Find(v); } vis[u]=1; f[u]=fa; } int main(){ n=read();m=read();root=read(); memset(head,-1,sizeof(head)); memset(h,-1,sizeof(h)); rep(i,1,n)f[i]=i; rep(i,1,n-1){ int x=read(),y=read(); insert_edge(x,y); } rep(i,1,m){ int x=read(),y=read(); insert_query(x,y); } dfs(root,root); rep(i,1,m)printf("%d\\n",ans[i]); return 0; }
以上是关于LCA(最近公共祖先)的主要内容,如果未能解决你的问题,请参考以下文章