티스토리 뷰
1. 문제
https://www.acmicpc.net/problem/11438
2. 풀이
LCA를 구현하는 문제다. LCA는 최소 공통 조상을 구하는 문제다.
LCA를 구현하기 위해 현재 노드의 부모를 2차원 배열에 저장하는 방법과 1차원 배열에 저장하는 방법이 있다.
1) 부모를 2차원 배열에 저장
부모를 2차원 배열에 저장할 경우 첫번째 차원에는 노드의 인덱스가 담기고 두번째 차원에는 노드의 2^i번째 조상 노드가 저장된다.
2) 부모를 1차원 배열에 저장
이렇게 하면 1차원 배열에는 현재 인덱스의 바로 위 부모가 담긴다. 이를 사용해 풀이 할 경우, while문을 사용해서 둘의 depth가 같을 때 까지 부모노드로 올려주면 된다.
+) 더 자세한 설명은.... 추후에.....
3. 코드
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
// LCA
public class Main_11438 {
static List<List<Integer>> arr; // 인접리스트 그래프
static int[] depth; // 노드의 depth 저장
static int[][] parents; // depth별 부모노드 저장
static int n;
static int k;
// 노드 depth와 노드의 부모 노드 저장
private static void dfs(int node, int cnt) {
depth[node] = cnt; // root의 depth는 1
for(int next : arr.get(node)) {
if(depth[next] == 0) {
parents[next][0] = node;
dfs(next, cnt + 1);
}
}
}
// 노드별 2^i 번째 조상노드 저장
private static void fillParents() {
for(int i = 1; i < k; i++) {
for(int j = 1; j <= n; j++) {
parents[j][i] = parents[parents[j][i-1]][i-1];
}
}
}
private static int lca(int a, int b) {
// depth가 낮은쪽을 기준으로 설정
if(depth[a] < depth[b]) {
int tmp = a;
a = b;
b = tmp;
}
// depth가 큰 a의 depth를 b의 depth를 맞추고
// 맞춘 depth의 조상노드로 대체
for(int i = k - 1; i >= 0; i--) {
if(Math.pow(2, i) <= depth[a] - depth[b])
a = parents[a][i];
}
// depth 맞춘 후 조상노드가 b면 (= a의 조상노드가 b면) 종료
if(a == b)
return a;
else {
// 두 노드는 같은 depth이므로
// 같이 2승씩 올라가며 공통부모 바로 아래까지 올라감
for(int i = k - 1; i >= 0; i--) {
if(parents[a][i] != parents[b][i]) {
a = parents[a][i];
b = parents[b][i];
}
}
}
return parents[a][0];
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
n = Integer.parseInt(br.readLine());
// 최대 depth 구하기
k = 0;
int tmp = 1;
while(tmp <= n) {
tmp <<= 1;
k++;
}
depth = new int[n+1]; // i 노드의 depth 저장, root는 1
parents = new int[n+1][k]; // depth별 부모노드 저장
arr = new ArrayList<List<Integer>>();
for(int i = 0; i <= n; i++)
arr.add(new ArrayList<Integer>());
for(int i = 0; i < n - 1; i++) { // 연결된 노드 저장
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
arr.get(a).add(b);
arr.get(b).add(a);
}
dfs(1, 1);
fillParents();
int m = Integer.parseInt(br.readLine());
for(int i = 0; i < m; i++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int lca = lca(a, b);
bw.write(lca + "\n");
}
bw.flush();
bw.close();
br.close();
}
}
'알고리즘 > 백준' 카테고리의 다른 글
[JAVA/다익스트라] 백준 5719 거의 최단 경로 (0) | 2021.07.15 |
---|---|
[JAVA/LCA] 백준 3176 도로 네트워크 (0) | 2021.07.15 |
[JAVA/플로이드 와샬] 백준 2458 키순서 (0) | 2021.07.12 |
[JAVA/투포인터] 백준 2143 두 배열의 합 (0) | 2021.07.11 |
[JAVA/백트래킹] 백준 9663 N-Queen (0) | 2021.07.11 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 자바
- java
- hc-06
- 프로그래머스
- the pads
- 워드프레스
- c++
- 집배원 한상덕
- hackerrank
- BFS
- FTP
- 키 순서
- git
- DP
- ESP8266
- 구슬 탈출2
- 라즈베리파이
- 아두이노
- dovecot
- 블루투스
- 11503
- 2981
- 합승 택시 요금
- 리눅스
- 메일서버
- mysql
- dht11
- 백준
- 라즈비안
- 스티커모으기2
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함