728x90
⬛ 백준 11437번. LCA 1 - 최소 공통 조상 문풀
https://www.acmicpc.net/problem/11437
문제
N(2 ≤ N ≤ 50,000)개의 정점으로 이루어진 트리가 주어진다. 트리의 각 정점은 1번부터 N번까지 번호가 매겨져 있으며, 루트는 1번이다.
두 노드의 쌍 M(1 ≤ M ≤ 10,000)개가 주어졌을 때, 두 노드의 가장 가까운 공통 조상이 몇 번인지 출력한다.
입력
첫째 줄에 노드의 개수 N이 주어지고, 다음 N-1개 줄에는 트리 상에서 연결된 두 정점이 주어진다. 그 다음 줄에는 가장 가까운 공통 조상을 알고싶은 쌍의 개수 M이 주어지고, 다음 M개 줄에는 정점 쌍이 주어진다.
출력
M개의 줄에 차례대로 입력받은 두 정점의 가장 가까운 공통 조상을 출력한다.
💚 문제 접근 방식
LCA를 푸는 방법은 크게 2가지가 있다. 이 문제의 경우 질의 개수 10,000개, 노드 개수 50,000개 여서 비교적 데이터 크기가 큰 문제는 아니다. 따라서 일반적인 LCA 풀이 방식으로 구현할 수 있다.
1) 데이터 초기화하기
노드 N개에 대한 간선 N-1개의 정보를 양방향 간선으로 tree 에 담아준다.
visited, parent, depth 선언해준다.
DFS나 BFS로 트리의 루트부터 탐색하면서 각 노드의 (부모노드, 깊이) 정보 담아준다.
2) getLCA(a,b)로 두 노드의 LCA를 구해주기
→ (1) 더 깊이 큰 노드를 a 에 swap
→ (2) 깊이 큰 a노드의 깊이를 b와 같아질 때까지 parent 거슬러 올라감
→ (3) 깊이 같아진 상태에서는 a==b 될 때까지 동시에 한 칸씩 거슬러 올라가다가 같아지면 return a (=LCA)
💚 제출 코드
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/**
* 11437번. 최소공통조상구하기 1 - LCA 문풀
* @author MYLG
*
*/
public class Main {
static ArrayList<ArrayList<Integer>> tree;
static int[] parent;
static int[] depth;
static boolean[] visited;
//BFS
private static void BFS(int root) {
Queue<Integer> Q = new LinkedList<>();
Q.offer(root);
visited[root] = true;
while(!Q.isEmpty()) {
int cur = Q.poll();
for(int nx : tree.get(cur)) {
if(!visited[nx]) {
visited[nx] = true;
Q.offer(nx);
parent[nx] = cur;
depth[nx] = depth[cur] + 1;
}
}
}
}
//getLCA
private static int getLCA(int a, int b) {
//깊이 더 큰 애를 a에 담기
if(depth[a] < depth[b]) {
int tmp = a;
a = b;
b = tmp;
}
//깊이 같아질 때까지 맞추기
while(depth[a] != depth[b]) {
a = parent[a];//계속 올림(더 깊이 높은 애를)
}
//맞춰서 탈출했으면 이제 동시에 한 칸씩 올림
while(a != b) {
a = parent[a];
b = parent[b];
}
return a;
}
//실행 메인
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner kb = new Scanner(System.in);
int N = kb.nextInt();
parent = new int[N+1];
depth = new int[N+1];
visited = new boolean[N+1];
tree = new ArrayList<>();
for(int i=0; i<=N; i++) {
tree.add(new ArrayList<>());
}
for(int i=0; i<N-1; i++) {
int a = kb.nextInt();
int b = kb.nextInt();
//양방향 간선 채우기
tree.get(a).add(b);
tree.get(b).add(a);
}
BFS(1);//정보 담기
//2) LCA 구하기
int M = kb.nextInt();
for(int i=0; i<M; i++) {
int a = kb.nextInt();
int b = kb.nextInt();
System.out.println(getLCA(a, b));
}
}
}
728x90
'코딩 테스트 [준비] > [문풀] Baekjoon_백준 문풀_조지기' 카테고리의 다른 글
백준 | 2211번. 네트워크 복구 - 다익스트라 문풀 (java) (33) | 2024.05.09 |
---|---|
백준 | 11438번. LCA 2 - 최소 공통 조상 문풀 (65) | 2024.02.14 |
백준 | 11505번. 구간 곱 구하기 - 세그먼트 트리 문풀 (3) | 2024.02.14 |
백준 | 10868번. 최솟값 찾기 2 - 세그먼트 트리 문풀 (61) | 2024.02.14 |
백준 | 2042번. 구간합 구하기 3 - 세그먼트 트리 문풀 (55) | 2024.02.14 |