首页 > 代码库 > LCA在线处理 基于二分搜索

LCA在线处理 基于二分搜索

记节点v到根点的深度为depth[v],那么当w是v和u的最近公共祖先时,可以想让v和u在同一个深度,即让深度高的走|depth[v]-depth[u]|然后一起走,

直到遇见相同的祖先时就是最近公共祖先了。如果是计算一次的话还可以,但有很多询问时就不行了。

那么可以利用父亲节点的信息来做了,可以通过parent2[v] = parent[parent[v]]得到v向上走两步的节点。在利用这个信息,

又可以通过parent4[v] = parent2[parent2[v]]得到向上走4步得到的节点,这样搜索的复杂度是O(long(n))了,预处理parent[k][v]的复杂度是O(nlong(n))。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <vector>
 4 #include <string.h>
 5 using namespace std;
 6 const int N = 1e4+10;
 7 vector<int> G[N];
 8 int vis[N], parent[30][N], depth[N], t, n;
 9 
10 void dfs(int v, int p, int d){
11     parent[0][v] = p;
12     depth[v] = d;
13     for(int i = 0; i < G[v].size(); i ++){
14         if(G[v][i] != p) dfs(G[v][i],v,d+1);
15     }
16 }
17 int lca(int u, int v){
18     if(depth[u] > depth[v]) swap(u,v);
19     for(int k = 0; k < 30; k ++){
20         if((depth[v]-depth[u]) >> k&1){
21             v = parent[k][v];
22         }
23     }
24     if(v == u) return u;
25     for(int k = 29; k >= 0; k--){
26         if(parent[k][u] != parent[k][v]){
27             u = parent[k][u];
28             v = parent[k][v];
29         }
30     }
31     return parent[0][u];
32 }
33 void init(){
34     memset(parent,-1,sizeof(parent));
35     for(int i = 1; i < N; i ++){
36         parent[0][i] = i;
37         G[i].clear();
38     }
39     memset(vis,0,sizeof(vis));
40     memset(depth,0,sizeof(depth));
41 }
42 int main(){
43     scanf("%d",&t);
44     while(t--){
45         scanf("%d",&n);
46         init();
47         int x, y;
48         for(int i = 1; i < n; i ++){
49             scanf("%d %d",&x,&y);
50             G[x].push_back(y);
51             G[y].push_back(x);
52             vis[y] = 1;
53         }
54         for(int i = 1; i <= n; i ++){
55             if(!vis[i]){
56                 dfs(i,-1,0);
57                 for(int k = 0; k+1 < 30; k ++){
58                     for(int v = 0; v < N; v ++){
59                         if(parent[k][v] < 0) parent[k+1][v] = -1;
60                         else parent[k+1][v] = parent[k][parent[k][v]];
61                     }
62                 }
63             }
64         }
65         scanf("%d%d",&x,&y);
66         printf("%d\n",lca(x,y));
67     }
68     return 0;
69 }

 

LCA在线处理 基于二分搜索