https://www.cnblogs.com/violet-acmer/p/9686774.html
参考资料:
http://dongxicheng.org/structure/lca-rmq/
挑战程序设计竞赛(第二版)
变量解释:
对有根树进行DFS,将遍历到的节点按照顺序记下,我们将得到一个长度为2N-1的序列,称之为欧拉序列。
total : 记录dfs遍历过程中回溯的节点编号,其实就是从0->2N-1。
vs[ ] : 记录DFS访问的顺序,也就是欧拉序列。
depth[ ] : 记录访问到的节点的深度。
pos[ ] : 记录各个顶点在va[ ] 中首次出现的下标。
AC代码献上:
基于RMQ的LCA
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<vector> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdio> 6 using namespace std; 7 #define pb(x) push_back(x) 8 const int maxn=10010; 9 10 int n; 11 int total; 12 int root; 13 int vs[2*maxn-1];//最多需要记录 2*n-1个数 14 int depth[2*maxn-1]; 15 int pos[maxn]; 16 vector<int >edge[maxn]; 17 18 //==========RMQ========== 19 struct RMQ 20 { 21 int dp[20][2*maxn-1]; 22 void Pretreat()//预处理dp[0][] 23 { 24 for(int i=0;i < total;++i) 25 dp[0][i]=i; 26 } 27 void ST()//ST表中记录的是使区间[i,j]的 depth[ ]值最小的下标,级dp[][]存储的是下标,而不是最小值 28 { 29 //欧拉序列中一共有total个数 30 //2^k == total -> k=log2(total) (以2为底),但计算机中的log是以e为底的 31 //由换底公式可得 k = log(total)/log(2) 32 int k=log(total)/log(2); 33 for(int i=1;i <= k;++i) 34 for(int j=0;j <= (total-(1<<i));++j) 35 if(depth[dp[i-1][j]] > depth[dp[i-1][j+(1<<(i-1))]]) 36 dp[i][j]=dp[i-1][j+(1<<(i-1))];//记录的是使depth[ ]最小的下标 37 else 38 dp[i][j]=dp[i-1][j]; 39 } 40 int LCA(int u,int v) 41 { 42 if(u > v) 43 swap(u,v); 44 int k=log(v-u+1)/log(2); 45 if(depth[dp[k][u]] > depth[dp[k][v-(1<<k)+1]]) 46 return vs[dp[k][v-(1<<k)+1]]; 47 return vs[dp[k][u]]; 48 } 49 }_rmq; 50 //======================= 51 void Dfs(int v,int f,int d) 52 { 53 pos[v]=total; 54 vs[total]=v; 55 depth[total++]=d; 56 for(int i=0;i < edge[v].size();++i) 57 { 58 int to=edge[v][i]; 59 if(to != f) 60 { 61 Dfs(to,v,d+1); 62 vs[total]=v; 63 depth[total++]=d; 64 } 65 } 66 } 67 void Init() 68 { 69 total=0; 70 root=0; 71 for(int i=1;i <= n;++i) 72 edge[i].clear(); 73 } 74 75 int main() 76 { 77 int T; 78 scanf("%d",&T); 79 while(T--) 80 { 81 scanf("%d",&n); 82 Init(); 83 for(int i=1;i < n;++i) 84 { 85 int u,v; 86 scanf("%d%d",&u,&v); 87 edge[u].pb(v); 88 root=(root == 0 || root == v ? u:root); 89 } 90 Dfs(root,-1,0); 91 _rmq.Pretreat(); 92 _rmq.ST(); 93 int u,v; 94 scanf("%d%d",&u,&v); 95 printf("%d ",_rmq.LCA(pos[u],pos[v])); 96 } 97 return 0; 98 }