728x90
최소 공통 조상(LCA: Lowest Common Ancestor)
트리 상의 두 노드 a,b가 있을 때, 두 노드의 가장 가까운 공통 조상 노드 => 최소 공통 조상

풀이 방법
- 모든 노드의 부모, 깊이 기록(DFS 또는 BFS)
// DFS로 부모와 깊이 채우기
static void dfs(int current, int d) {
visited[current] = true;
depth[current] = d;
for (int next : tree[current]) {
if (!visited[next]) {
parent[next] = current;
dfs(next, d + 1);
}
}
}
dfs(1,0); //시작 노드 1, 깊이 0


2. 두 노드를 같은 깊이로 맞춤
while (depth[a] > depth[b]) a = parent[a];
while (depth[b] > depth[a]) b = parent[b];
3. 위로 올라가면서 공통 조상 찾기
static int lca(int a, int b) {
// 깊이를 같게 맞춤
while (depth[a] > depth[b]) a = parent[a];
while (depth[b] > depth[a]) b = parent[b];
// 공통 조상 만날 때까지 위로 이동
while (a != b) {
a = parent[a];
b = parent[b];
}
return a;
}

전체 코드
import java.io.*;
import java.util.*;
public class Main {
static int N, M;
static List<Integer>[] tree;
static int[] parent;
static int[] depth;
static boolean[] visited;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
tree = new ArrayList[N + 1];
for (int i = 1; i <= N; i++) tree[i] = new ArrayList<>();
// 간선 입력 받기
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());
tree[a].add(b);
tree[b].add(a);
}
parent = new int[N + 1];
depth = new int[N + 1];
visited = new boolean[N + 1];
// 루트는 1번 노드
dfs(1, 0);
M = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
// 쿼리 처리
for (int i = 0; i < M; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int u = Integer.parseInt(st.nextToken());
int v = Integer.parseInt(st.nextToken());
sb.append(lca(u, v)).append("\n");
}
System.out.print(sb);
}
// DFS로 부모와 깊이 채우기
static void dfs(int current, int d) {
visited[current] = true;
depth[current] = d;
for (int next : tree[current]) {
if (!visited[next]) {
parent[next] = current;
dfs(next, d + 1);
}
}
}
// LCA 찾기
static int lca(int a, int b) {
// 깊이를 같게 맞춤
while (depth[a] > depth[b]) a = parent[a];
while (depth[b] > depth[a]) b = parent[b];
// 공통 조상 만날 때까지 위로 이동
while (a != b) {
a = parent[a];
b = parent[b];
}
return a;
}
}728x90
'백준' 카테고리의 다른 글
| [JAVA] 백준 골드4 1987 알파벳 (0) | 2025.05.15 |
|---|---|
| 그리디(Greedy) 알고리즘 (0) | 2023.07.15 |
| 백준 10814번 C++ pair, stable_sort 사용해서 해결 (0) | 2023.07.05 |
| 백준 1463번 C++ , 다이나믹 프로그래밍으로 풀기 (0) | 2023.06.29 |
| [자료구조] 스택(STACK), 큐(QUEUE) (0) | 2023.06.21 |