programming-examples/java/Data_Structures/LcaSparseTable.java

66 lines
1.4 KiB
Java
Raw Normal View History

2019-11-15 12:59:38 +01:00
import java.util.*;
import java.util.stream.Stream;
// Answering LCA queries in O(1) with O(n*log(n)) preprocessing
public class LcaSparseTable {
int len;
int[][] up;
int[] tin;
int[] tout;
int time;
void dfs(List<Integer>[] tree, int u, int p) {
tin[u] = time++;
up[0][u] = p;
for (int i = 1; i < len; i++)
up[i][u] = up[i - 1][up[i - 1][u]];
for (int v : tree[u])
if (v != p)
dfs(tree, v, u);
tout[u] = time++;
}
public LcaSparseTable(List<Integer>[] tree, int root) {
int n = tree.length;
len = 1;
while ((1 << len) <= n) ++len;
up = new int[len][n];
tin = new int[n];
tout = new int[n];
dfs(tree, root, root);
}
boolean isParent(int parent, int child) {
return tin[parent] <= tin[child] && tout[child] <= tout[parent];
}
public int lca(int a, int b) {
if (isParent(a, b))
return a;
if (isParent(b, a))
return b;
for (int i = len - 1; i >= 0; i--)
if (!isParent(up[i][a], b))
a = up[i][a];
return up[0][a];
}
// Usage example
public static void main(String[] args) {
List<Integer>[] tree = Stream.generate(ArrayList::new).limit(5).toArray(List[]::new);
tree[0].add(1);
tree[1].add(0);
tree[1].add(2);
tree[2].add(1);
tree[3].add(1);
tree[1].add(3);
tree[0].add(4);
tree[4].add(0);
LcaSparseTable t = new LcaSparseTable(tree, 0);
System.out.println(1 == t.lca(3, 2));
System.out.println(0 == t.lca(2, 4));
}
}