介绍一种解决最近公共祖先的在线算法,st表,它是建立在线性中的rmq问题之上。
代码:
1 //LCA: DFS+ST(RMQ) 2 3 #include<cstdio> 4 #include<cctype> 5 #include<iostream> 6 using namespace std; 7 8 const int size=500010; 9 int n,m,s,tot; 10 int first[size],log[size<<1],f[size<<1][60],head[size<<1],p[size<<1][60]; 11 bool vis[size]; 12 struct node1 13 { 14 int path,depth; 15 }a[size*2]; 16 struct node2 17 { 18 int next,to; 19 }e[size*2]; 20 21 inline int read() 22 { 23 int x=0,f=1; 24 char c=getchar(); 25 while (!isdigit(c)) 26 f=c=='-'?-1:1,c=getchar(); 27 while (isdigit(c)) 28 x=(x<<1)+(x<<3)+(c^48),c=getchar(); 29 return x*f; 30 } 31 32 inline int write(int x) 33 { 34 if (x<0) 35 x=-x; 36 if (x>9) 37 write(x/10); 38 putchar(x%10+48); 39 } 40 41 inline void add(int from,int to) 42 { 43 ++tot; 44 e[tot].to=to; 45 e[tot].next=head[from]; 46 head[from]=tot; 47 } 48 49 inline void logn() 50 { 51 int i; 52 log[0]=-1; 53 for (i=1;i<=n*2+1;i++) 54 log[i]=log[(i>>1)]+1; 55 } 56 57 inline void DFS(int x,int dep) 58 { 59 a[++tot].path=x; 60 a[tot].depth=dep; 61 first[x]=tot; 62 vis[x]=true; 63 for (int i=head[x];i;i=e[i].next) 64 if (!vis[e[i].to]) 65 { 66 DFS(e[i].to,dep+1); 67 a[++tot].path=x; 68 a[tot].depth=dep; 69 } 70 } 71 72 inline void ST() 73 { 74 int i,j; 75 for (i=1;i<=tot;i++) 76 f[i][0]=i; 77 for (j=1;j<=log[tot];j++) 78 for (i=1;i+(1<<j)<=tot;i++) 79 { 80 if (a[f[i][j-1]].depth<a[f[i+(1<<j-1)][j-1]].depth) 81 f[i][j]=f[i][j-1]; 82 else 83 f[i][j]=f[i+(1<<j-1)][j-1]; 84 } 85 } 86 87 inline int RMQ(int l,int r) 88 { 89 int w=log[r-l+1]; 90 return a[f[l][w]].depth<a[f[r-(1<<w)+1][w]].depth?f[l][w]:f[r-(1<<w)+1][w]; 91 } 92 93 inline int LCA(int u,int v) 94 { 95 int x=first[u],y=first[v]; 96 if (x>y) 97 swap(x,y); 98 return a[RMQ(x,y)].path; 99 } 100 101 int main() 102 { 103 int i,j,x,y; 104 n=read(); 105 m=read(); 106 s=read(); 107 logn(); 108 for (i=1;i<n;i++) 109 { 110 x=read(); 111 y=read(); 112 add(x,y); 113 add(y,x); 114 } 115 tot=0; 116 DFS(s,1); 117 ST(); 118 while (m--) 119 { 120 x=read(); 121 y=read(); 122 write(LCA(x,y)); 123 putchar(10); 124 } 125 return 0; 126 }