LuoGu P3379最近公共父祖先--倍增法 Java实现
我觉得比tarjan要简单。
在进行连续询问输出地时候,不要使用System.out.println().先把结果记录在StringBuilder里面。(我就是因为这样子,所以超时了,还奇怪地找了好长时间原因。)
因为网上有很详细的讲解,这里就是记录一下自己的练习。
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.StringTokenizer;
public class Main {
static LinkedList<Integer>[] adj;
static int[] depth;
static int[][] jumpParent;
static int maxLevel;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
int s = Integer.parseInt(st.nextToken());
adj = new LinkedList[n + 1];
for (int i = 0; i <= n; i++) {
adj[i] = new LinkedList<>();
}
int a, b;
for (int i = 1; i < n; i++) {
st = new StringTokenizer(br.readLine());
a = Integer.parseInt(st.nextToken());
b = Integer.parseInt(st.nextToken());
adj[a].add(b);
adj[b].add(a);
}
depth = new int[n + 1];
ArrayDeque<Integer> ad = new ArrayDeque<>();
ad.addLast(s);
depth[s] = 1;
boolean[] isVisit = new boolean[n + 1];
int curr;
int maxDepth = 0;
int[] father = new int[n + 1];
father[s] = s;
while (!ad.isEmpty()) {
curr = ad.pollFirst();
isVisit[curr] = true;
for (int next : adj[curr]) {
if (!isVisit[next]) {
ad.addLast(next);
depth[next] = depth[curr] + 1;
maxDepth = Math.max(depth[next], maxDepth);
father[next] = curr;
}
}
}
maxLevel = 0;
while (Math.pow(2, maxLevel) < maxDepth) {
maxLevel++;
}
maxLevel++;
jumpParent = new int[n + 1][maxLevel + 1];
for (int j = 0; j <= maxLevel; j++) {
for (int i = 1; i <= n; i++) {
if (j == 0) {
jumpParent[i][j] = father[i];
continue;
}
jumpParent[i][j] = jumpParent[jumpParent[i][j - 1]][j - 1];
}
}
StringBuilder bu = new StringBuilder();
for (int i = 1; i <= m; i++) {
st = new StringTokenizer(br.readLine());
a = Integer.parseInt(st.nextToken());
b = Integer.parseInt(st.nextToken());
bu.append(LCA(a,b)).append("\n");
}
System.out.println(bu.toString());
}
private static int LCA(int a, int b) {
if (depth[a] < depth[b]) {
int temp = a;
a = b;
b = temp;
}
for (int i = maxLevel; i >= 0; i--) {
if (depth[jumpParent[a][i]] >= depth[b]) {
a = jumpParent[a][i];
}
}
if (a == b) {
return a;
}
for (int i = maxLevel; i >= 0; i--) {
if (jumpParent[a][i] != jumpParent[b][i]) {
a = jumpParent[a][i];
b = jumpParent[b][i];
}
}
return jumpParent[a][0];
}
}

浙公网安备 33010602011771号