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 }
时间: 2024-08-30 01:00:00

LCA在线处理 基于二分搜索的相关文章

hihocoder1069最近公共祖先&#183;三(LCA在线算法--DFS+RMQ-ST)

树上任意两点的最近祖先,必定就是这两个节点的最短路径上深度最小的那个点. 例如:下图中,节点7和5,其最短路径为7--4--1--5, 这条路径上深度最小的点为节点1,其深度为1.节点1即为节点7和5的LCA. 因此,要找到任意两个节点的LCA,只需要先找到上述最短路径,再找到最短路径中深度最小的点.而这下面所述LCA在线算法所做的事. LCA在线算法描述(以上图为例): 1.获得“最短路径”(并不是真正的一条路径,包含其他节点,但不影响算法的正确性) 采用DFS遍历整棵树,得到以下数据: (1

LCA在线算法ST算法

求LCA(最近公共祖先)的算法有好多,按在线和离线分为在线算法和离线算法. 离线算法有基于搜索的Tarjan算法较优,而在线算法则是基于dp的ST算法较优. 首先说一下ST算法. 这个算法是基于RMQ(区间最大最小值编号)的,不懂的可以这里学习一些 而求LCA就是把树通过深搜得到一个序列,然后转化为求区间的最小编号. 比如说给出这样一棵树. 我们通过深搜可以得到这样一个序列: 节点ver 1 3 1 2 5 7 5 6 5 2 4 2 1 (先右后左) 深度R 1 2 1 2 3 4 3 4 3

poj 1330 Nearest Common Ancestors lca 在线rmq

Nearest Common Ancestors Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below:  In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree.

lca 在线,离线 poj 1330

题目链接:Nearest Common Ancestors 在线做法: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> using namespace std; const int maxn=10000+10; const int M=20; struct no

LCA在线算法详解

LCA(最近公共祖先)的求法有多种,这里先介绍第一种:在线算法. 声明一下:下面的内容参考了http://www.cnblogs.com/scau20110726/archive/2013/05/26/3100812.html. 在线算法就是利用了DFS和RMQ两种算法,它先是预处理好所有情况,然后根据输入输出答案,在输入比较多的时候用比较好. 上面两张图介绍了在线算法的做法,要理解并不难,下面附上实现代码: 1 /******************************* 2 dfs实现代

LCA 在线倍增法 求最近公共祖先

第一步:建树  这个就不说了 第二部:分为两步  分别是深度预处理和祖先DP预处理 DP预处理: int i,j; for(j=1;(1<<j)<n;j++) for(int i=0;i<n;++i) if(fa[i][j]=-1) fa[i][j]=fa[fa[i][j-1]][j-1];/*DP处理出i的2^j祖先是谁*/ 深度预处理: 1 void dfs(int now,int from,int deepth) 2 { 3 deep[now]=deepth; 4 for(i

Html在线编辑器--基于Jquery的xhEditor轻量级编辑器

xhEditor是一个基于jQuery开发的简单迷你并且高效的可视化XHTML编辑器,基于网络访问并且兼容IE 6.0-8.0.Firefox 3.0.Opera 9.6.Chrome 1.0.Safari 3.22 Features(特点): Small:初始加载5个文件,包括:1个js(36k)+2个css(6k)+2个图片(4k),总共46k.若js和css文件进行gzip压缩,可以进一步缩减为18k左右. Fast:基于jQuery引擎开发,提供高效的代码执行效率 Simple:简单的调

HDU 2586 How far away ?(LCA在线算法实现)

http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵树,求出树上任意两点之间的距离. 思路: 这道题可以利用LCA来做,记录好每个点距离根结点的距离,然后只要计算出两点的LCA,这样一来答案就是distance[u]+distance[v]-2distance[LCA]. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #includ

lca 在线算法 zoj 3195

题目链接:Design the city 题目大意是对给定3点,求这三个点只之间的最短距离.三个点两两组合求lca:dis[u]+dis[v]-dis[lca];将三个组合值相加除以2即为答案. RMQ算法学习:http://blog.csdn.net/liang5630/article/details/7917702 对于lca->RMQ的转化,可以参看巨巨写的ppt. 欧拉序列:euler[N]; 深度序列:depth[N]; #include <iostream> #include