介绍一种解决最近公共祖先的在线算法,倍增,它是建立在任意整数的二进制拆分之上。
代码:
1 //LCA:Doubly 2 3 #include<cstdio> 4 #define swap(a,b) a^=b^=a^=b 5 #define maxn 500010 6 using namespace std; 7 8 int n,m,s,tot,head[maxn],deep[maxn],p[maxn][20]; 9 struct node 10 { 11 int nxt,to; 12 }edge[maxn<<1]; 13 14 int read() 15 { 16 int x=0,f=1; 17 char c=getchar(); 18 while (c<48||c>57) 19 f=c=='-'?-1:1,c=getchar(); 20 while (c>=48&&c<=57) 21 x=(x<<1)+(x<<3)+(c^48),c=getchar(); 22 return x*f; 23 } 24 25 void write(int x) 26 { 27 if (x<0) 28 x=-x,putchar('-'); 29 if (x>=10) 30 write(x/10); 31 putchar(x%10+48); 32 } 33 34 void add(int a,int b) 35 { 36 edge[++tot]=(node){head[a],b}; 37 head[a]=tot; 38 edge[++tot]=(node){head[b],a}; 39 head[b]=tot; 40 } 41 42 void init() 43 { 44 for (int j=1;(1<<j)<=n;j++) 45 for (int i=1;i<=n;i++) 46 if (p[i][j-1]) 47 p[i][j]=p[p[i][j-1]][j-1]; 48 } 49 50 int dfs(int u) 51 { 52 for (int i=head[u];i;i=edge[i].nxt) 53 if (!deep[edge[i].to]) 54 { 55 deep[edge[i].to]=deep[u]+1; 56 p[edge[i].to][0]=u; 57 dfs(edge[i].to); 58 } 59 } 60 61 int LCA(int a,int b) 62 { 63 if (deep[a]<deep[b]) 64 swap(a,b); 65 int i,j; 66 for (i=0;(1<<i)<=deep[a];i++); 67 i--; 68 for (j=i;j>=0;j--) 69 if (deep[b]<=deep[a]-(1<<j)) 70 a=p[a][j]; 71 if (a==b) 72 return a; 73 for (j=i;j>=0;j--) 74 if (p[a][j]!=p[b][j]&&deep[p[a][j]]>=1) 75 { 76 a=p[a][j]; 77 b=p[b][j]; 78 } 79 return p[a][0]; 80 } 81 82 int main() 83 { 84 int i,j,k; 85 n=read(),m=read(),s=read(); 86 for (i=1;i<=n-1;i++) 87 add(read(),read()); 88 deep[s]=1; 89 dfs(s); 90 init(); 91 while (m--) 92 write(LCA(read(),read())),putchar(10); 93 return 0; 94 }