문제 설명
문제 풀이
- 일반적인 LCA 문제이다.
- O(N) 알고리즘을 사용해도 괜찮아 보여서 사용했다.
- 풀이는 아래와 같다.
- 트리를 루트부터 DFS를 진행하여 각 노드의 깊이, 부모 노드를 저장해준다.
- 두개의 노드가 주어졌을 때 우선 두 노드의 높이가 같아질 때까지 한쪽을 계속 부모 노드로 이동 시킴.
- 같은 높이에서 부터 두 노드의 부모를 동시에 탐색하며 노드가 같아질 경우 LCA
소스 코드 (JAVA)
import java.io.*;
import java.util.*;
class Main {
static int N, M;
static int[] depth, parent;
static List<List<Integer>> map = new ArrayList<>();
static int solve(int a, int b) {
while(depth[a] > depth[b]) {
a = parent[a];
}
while(depth[a] < depth[b]) {
b = parent[b];
}
while(a != b) {
a = parent[a];
b = parent[b];
}
return a;
}
static void init(int cur, int dep, int before) {
depth[cur] = dep;
parent[cur] = before;
for (int i = 0; i < map.get(cur).size(); i++) {
int next = map.get(cur).get(i);
if (next != before) init(next, dep+1, cur);
}
}
static void input() throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
for (int i = 0; i <= N; i++)
map.add(new ArrayList<>());
depth = new int[N+1];
parent = new int[N+1];
for (int i = 0; i < N - 1; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
map.get(a).add(b);
map.get(b).add(a);
}
init(1, 1, 0);
M = Integer.parseInt(br.readLine());
for (int i = 0; i < M; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
bw.write(solve(a, b) + "\n");
}
bw.flush();
}
public static void main(String[] args) throws IOException {
input();
}
}