LCA就是最近公共祖先ios
對於有根樹\(Tree\)的兩個結點\(u、v\),最近公共祖先\(LCA(T,u,v)\)表示一個結點\(x\),知足\(x\)是\(u、v\)的祖先且\(x\)的深度儘量大。spa
解釋明天再寫code
#include<cstdio> #include<iostream> #include<cstring> using namespace std; const int maxn=500000+2; int n,m,root,k; int head[maxn],d[maxn]; struct node { int v,next; } e[maxn<<1]; void add(int u,int v) { e[k].v=v; e[k].next=head[u]; head[u]=k++; } //________________________________________ int f[maxn][21]; void dfs(int u,int fa) { d[u]=d[fa]+1;//更新深度,父親的深度加1 f[u][0]=fa;//跳2^0步到爸爸 for(int i=1; (1<<i)/*即2^i*/<=d[u]; ++i) { f[u][i]=f[f[u][i-1]][i-1];//敲黑板,看這裏,解釋放博客裏面 } for(int i=head[u]; i!=-1; i=e[i].next) { int v=e[i].v; if(v!=fa)//防止遞歸到爸爸 dfs(v,u);//遞歸下一層 } } int lca(int a,int b) { if(d[a]>d[b]) swap(a,b); for(int i=20; i>=0; --i) { if(d[a]<=d[b]-(1<<i)) b=f[b][i]; } if(a==b) return a; for(int i=20; i>=0; --i) { if(f[a][i]==f[b][i]) continue; else a=f[a][i],b=f[b][i]; } return f[a][0]; } int main() { memset(head,-1,sizeof(head)); cin>>n>>m>>root; for(int i=1; i<n; ++i) { int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(root,0); while(m--) { int a,b; scanf("%d%d",&a,&b); cout<<lca(a,b)<<'\n'; } return 0; }
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<vector> #include<map> #include<string> #include<cstring> using namespace std; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } const int maxn=500005; const int inf=0x7fffffff; struct Edge { int ne,to; } edge[maxn<<1]; int h[maxn],num_edge=0,t; inline void add_edge(int f,int to) { edge[++num_edge].ne=h[f]; edge[num_edge].to=to; h[f]=num_edge; return ; } int f[maxn][35],d[maxn]; int n,m,s; void bfs() { int u,v; memset(d,0,sizeof(d)); queue <int>q; q.push(s); d[s]=1; while(q.size()) { u=q.front(); q.pop(); for(int i=h[u]; i; i=edge[i].ne) { v=edge[i].to; if(d[v])continue; f[v][0]=u,d[v]=d[u]+1; for(int j=1; j<=t; j++) { f[v][j]=f[f[v][j-1]][j-1]; } q.push(v); } } return ; } inline int lca(int x,int y) { if(d[x]<d[y])swap(x,y); if(x==y)return x; for(int i=t; i>=0; i--) { if(d[f[x][i]]>=d[y])x=f[x][i]; } if(x==y)return x; for(int i=t; i>=0; i--) { if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; } return f[x][0]; } int main() { int x,y,z; n=read(),m=read(),s=read(); memset(f,0,sizeof(f)); t=(int)(log(n)/log(2))+1; for(int i=1; i<n; i++) { x=read(); y=read(); add_edge(x,y); add_edge(y,x); } bfs(); for(int i=1; i<=m; i++) { x=read(); y=read(); printf("%d\n",lca(x,y)); } return 0; }
解釋同上之後再寫遞歸
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<vector> #include<map> #include<string> #include<cstring> using namespace std; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } const int N=500001; int n,m,root,cnt; struct node { int u,v,next; }e[N<<1]; int head[N]; int son[N]; int f[N],d[N],s[N],c[N]; void add(int x,int y) { e[++cnt].u=x; e[cnt].v=y; e[cnt].next=head[x]; head[x]=cnt; } void dfs1(int n,int F) { s[n]=1;//初始化子樹大小爲1 d[n]=d[F]+1; f[n]=F; int V; for(int i=head[n];i;i=e[i].next) { V=e[i].v; if(V!=F) { dfs1(V,n); s[n]+=s[V]; if(s[son[n]]<s[V]) son[n]=V; } } } void dfs2(int n,int C) { c[n]=C; if(son[n]) dfs2(son[n],C); else return; int V; for(int i=head[n];i;i=e[i].next) { V=e[i].v; if(V!=f[n] && V!=son[n]) dfs2(V,V); } } int lca(int x,int y) { for(;c[x]!=c[y];x=f[c[x]]) { if(d[c[x]]<d[c[y]]) swap(x,y); } return d[x]<d[y]? x: y; } int main() { n=read();m=read();root=read(); for(int i=1;i<n;++i) { int x,y; x=read(); y=read(); add(x,y); add(y,x); } dfs1(root,0); dfs2(root,root); for(int i=1;i<=m;++i) { int x,y; x=read(); y=read(); cout<<lca(x,y)<<'\n'; } }