倍增法
1 /* 2 Source : 3 Problem : 求最近公共祖先的倍增算法 4 Solution : 5 Date :2018-08-16-16.45 6 */ 7 8 // #include <bits/stdc++.h> 9 #include<cstdio> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 using namespace std; 14 15 typedef long long LL; 16 const int MAXN = 100005; 17 const LL MOD7 = 1e9+7; 18 19 struct Edge 20 { 21 int u,v; 22 int next; 23 }edge[2*MAXN]; 24 int head[MAXN]; 25 int cnt; 26 int n; 27 28 void addEdge(int u,int v) 29 { 30 edge[cnt].u=u;edge[cnt].v=v;edge[cnt].next=head[u];head[u]=cnt++; 31 } 32 void init() 33 { 34 memset(head,-1,sizeof(head)); 35 cnt=0; 36 } 37 38 int dep[MAXN]; 39 int f[MAXN][20]; 40 41 void dfs(int u,int pre) 42 { 43 f[u][0]=pre; 44 for (int i=head[u];i!=-1;i=edge[i].next) 45 { 46 int v=edge[i].v; 47 // if (v==pre) continue; 48 dep[v]=dep[u]+1; 49 dfs(v,u); 50 } 51 } 52 53 void BZ() 54 { 55 for (int j=1;j<20;++j) 56 { 57 for (int i=1;i<=n;++i) 58 { 59 if (f[i][j-1]) 60 { 61 f[i][j]=f[f[i][j-1]][j-1]; 62 } 63 } 64 } 65 } 66 67 int LCA(int u,int v) 68 { 69 if (dep[u]<dep[v]) swap(u,v); 70 int delta = dep[u]-dep[v]; 71 for (int i=0;i<20;++i) 72 { 73 if (delta&(1<<i)) u = f[u][i]; 74 } 75 if (u==v) return u; 76 for (int i=19;i>=0;--i) 77 { 78 if (f[u][i]!=f[v][i]) 79 { 80 u=f[u][i]; 81 v=f[v][i]; 82 } 83 } 84 return f[u][0]; 85 } 86 87 int in[MAXN]; 88 89 int main() 90 { 91 #ifndef ONLINE_JUDGE 92 freopen("test.txt","r",stdin); 93 #endif // ONLINE_JUDGE 94 int Case; 95 scanf("%d",&Case); 96 while (Case--) 97 { 98 scanf("%d",&n); 99 init(); 100 int u,v; 101 int root=-1; 102 memset(in,0,sizeof(in)); 103 for (int i=1;i<n;++i) 104 { 105 scanf("%d%d",&u,&v); 106 addEdge(u,v); 107 in[v]++; 108 // f[v][0]=u; 109 } 110 for (int i=1;i<=n;++i) 111 if (in[i]==0) 112 { 113 root=i; 114 break; 115 } 116 dep[root]=1; 117 dfs(root,0); 118 BZ(); 119 int Q; 120 Q=1; 121 for (int i=1;i<=Q;++i) 122 { 123 scanf("%d%d",&u,&v); 124 printf("%d\n",LCA(u,v)); 125 } 126 } 127 return 0; 128 }