Skip to content

Commit 32995dd

Browse files
author
Dashdemberel Batchunag
committed
LCA java
1 parent 0cc3c84 commit 32995dd

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

Data Structures/LCA/lca.java

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import java.util.ArrayList;
2+
import java.util.Scanner;
3+
4+
public class lca {
5+
private final static int max = 100;
6+
private final static int height_max = 7;
7+
8+
int n;
9+
10+
private int[][] parent = new int[max][height_max]; //parent[v][k]: (2^k)-th ancestor of v
11+
private int[] level = new int[max]; //level counting from root
12+
private int[] log = new int[max]; //log[i] := [log_2(i)]
13+
//Incidence matrix of graph.
14+
private ArrayList<ArrayList<Integer>> graph = new ArrayList<>(max);
15+
16+
//pre-calculate [log_2(i)] for all i<max
17+
void updateLog() {
18+
for (int i = 2; i < max; i++) {
19+
log[i] = log[i / 2] + 1;
20+
}
21+
}
22+
23+
/* Set v as a parent of all the neighbors except p.
24+
* Repeat the step with dfs
25+
*/
26+
void dfsForParentAndLevels(int v, int p) {
27+
for (int sibling : graph.get(v)) {
28+
if (sibling != p) {
29+
//We are traversing away from the root.
30+
level[sibling] = level[v] + 1;
31+
//First(2^0-th) parent of sibling is v.
32+
parent[sibling][0] = v;
33+
dfsForParentAndLevels(sibling, v);
34+
}
35+
}
36+
}
37+
38+
void updateParents() {
39+
for (int k = 1; k <= log[n]; k++) {
40+
for (int v = 1; v <= n; v++) {
41+
parent[v][k] = parent[parent[v][k - 1]][k - 1];
42+
//(2^k)-th parent of v: 2^(k-1)-th parent of {2^(k-1)-th parent of v}
43+
}
44+
}
45+
}
46+
47+
//returns the lca of pair (u,v)
48+
int lca(int u, int v) {
49+
//We assume u is farther than v.
50+
if (level[u] < level[v]) {
51+
return lca(v, u);
52+
}
53+
//lca(u,v) is same as lca(u's 2^k-th parent, v),
54+
//as long as that parent is sits lower level than v.
55+
//so we can replace u with that parent.
56+
//we start with as biggest jump as possible.
57+
for (int k = log[n]; k >= 0; k--) {
58+
if (level[u] - (1 << k) >= level[v]) {
59+
u = parent[u][k];
60+
}
61+
}
62+
if (u == v) {
63+
//if we come to v after some possible jumps above
64+
//that means v is a direct ancestor of u. So the lca is v.
65+
return u;
66+
}
67+
//Now u and v are on the same level.
68+
//Again we start with the biggest possible jump.
69+
for (int k = log[n]; k >= 0; k--) {
70+
if (parent[u][k] != parent[v][k]) {
71+
//They must ascend together, until they have common parent.
72+
u = parent[u][k];
73+
v = parent[v][k];
74+
}
75+
}
76+
return parent[u][0];
77+
}
78+
79+
private void run() {
80+
final Scanner scan = new Scanner(System.in);
81+
82+
updateLog();
83+
int x, y;
84+
System.out.println("Let's build the tree first.\nEnter number of vertices: ");
85+
n = scan.nextInt();
86+
for (int i = 0; i <= n ; i++) {
87+
graph.add(new ArrayList<>());
88+
}
89+
90+
System.out.println("\nEnter " + (n-1) + " edge information, with 1-indexed. (u v)");
91+
for (int i = 1; i < n ; i++) {
92+
x = scan.nextInt();
93+
y = scan.nextInt();
94+
graph.get(x).add(y);
95+
graph.get(y).add(x);
96+
}
97+
98+
//mark vertex 1 as a root.
99+
//We set 1(itself) as its parent.
100+
dfsForParentAndLevels(1, 1);
101+
updateParents();
102+
103+
System.out.println("\nEnter the pair for lca: ");
104+
x = scan.nextInt();
105+
y = scan.nextInt();
106+
107+
System.out.println(lca(x, y) + "\n");
108+
}
109+
110+
public static void main(String[] args) {
111+
new lca().run();
112+
}
113+
114+
}

0 commit comments

Comments
 (0)