Description
Given a tree with a root, it requests a common ancestor that is directly closest to the specified two points.
Rokua P3379 "Template" recent public ancestor (LCA) solution
Every time I think of an array name, I think it's very difficult, so (causality.) Here, save the template offline algorithm Tarjan
#include <iostream> #include <cstdio> #include <cstring> #include <string> using namespace std;
int father[500005],visited[500005];
int n,m,s;
int head[500005],cnt=0,head1[500005],cnt1=0; struct node{int next,to;}
EDGES[1000005];
void Addedge (int u,int v) {Edges[cnt].next=head[u];
head[u]=cnt;
Edges[cnt++].to=v; } struct node1{int next,to,lca;}
EDGES1[1000005];
void Addedge1 (int u,int v) {Edges1[cnt1].next=head1[u];
Head1[u]=cnt1;
Edges1[cnt1++].to=v;
} int Getfather (int x) {if (father[x]==x) return x;
Father[x]=getfather (Father[x]);
return father[x];
} void _union (int x,int y) {int fx=getfather (x), Fy=getfather (y);
if (fx!=fy) father[fx]=fy;
} void Tarjan (int u) {visited[u]=1;
Father[u]=u;
for (int i=head[u];~i;i=edges[i].next) {int t=edges[i].to;
if (!visited[t]) {Tarjan (t);
_union (T,u);
}} for (int i=head1[u];~i;i=edges1[i].next) {int t=edges1[i].to;
if (Visited[t]) {edges1[i].lca=edges1[i^1].lca=getfather (t);
}}} int main () {memset (head,-1,sizeof (head));
memset (head1,-1,sizeof (HEAD1));
scanf ("%d%d%d", &n,&m,&s);
for (int i=1;i<n;i++) {int x, y;
scanf ("%d%d", &x,&y);
Addedge (x, y);
Addedge (Y,X);
} for (int i=1;i<=m;i++) {int A, B;
scanf ("%d%d", &a,&b);
Addedge1 (A, b);
Addedge1 (B,a);
} Tarjan (s);
for (int i=0;i<2*m;i+=2) {printf ("%d\n", EDGES1[I].LCA);
} return 0; }
Online algorithm RMQ
This feeling is easy to burst memory, at least in the cross-Valley template problem is Qwq
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cstdlib
> #define MIN (A, B) (A<B?A:B) using namespace std;
int n,m,s;
int head[500005],cnt=0,first[500005],dep[1000005];
int vertex[1000005],rmq[1000005][20],dfs_clock=0;
BOOL visited[500005]; struct node{int next,to;}
EDGES[1000005];
void Add (int u,int v) {Edges[cnt].next=head[u];
head[u]=cnt;
Edges[cnt].to=v;
cnt++;
} void Dfs (int u,int depth) {visited[u]=1;
++dfs_clock;first[u]=dfs_clock;
Vertex[dfs_clock]=u;
dep[dfs_clock]=depth;
for (int i=head[u];~i;i=edges[i].next) {int t=edges[i].to;
if (!visited[t]) {DFS (t,depth+1);
Vertex[++dfs_clock]=u;
dep[dfs_clock]=depth;
}}} void Rmqinit () {for (int i=1;i<=dfs_clock;i++) rmq[i][0]=i; for (int j=1, (1<<j) <=dfs_clock;j++) for (int i=1;i+ (1<<J) -1<=dfs_clock;i++) {if (dep[rmq[i][j-1]]<dep[rmq[i+ (1<< (j-1))][j-1]]) rmq[i][j]=rmq[i][j-1];
Else rmq[i][j]=rmq[i+ (1<< (j-1))][j-1];
}} int RMQ (int x,int y) {int l=first[x],r=first[y];
if (l>r) swap (L,R);
int k=0;
while ((1<< (k+1)) <=r-l+1) k++;
int a=rmq[l][k],b=rmq[r-(1<<k) +1][k];
if (Dep[a]<dep[b]) return A;
return b;
} int main () {memset (head,-1,sizeof (head));
scanf ("%d%d%d", &n,&m,&s);
int x, y;
for (int i=1;i<n;i++) {scanf ("%d%d", &x,&y);
Add (x, y);
Add (y,x);
} dfs (s,1);
Rmqinit ();
for (int i=1;i<=m;i++) {scanf ("%d%d", &x,&y);
printf ("%d\n", VERTEX[RMQ (x, y)]);
} return 0; }