poj 1330(RMQ&LCA入门题)

传送门:Problem 1330

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

 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\n",_rmq.LCA(pos[u],pos[v]));
96     }
97     return 0;
98 }
View Code

猜你喜欢

转载自www.cnblogs.com/violet-acmer/p/9697883.html