최소 공통 조상 예제 - 1
Last updated
Last updated
n(수의 개수)
tree(트리 데이터 저장)
for n-1 반복:
tree 인접 리스트에 데이터 저장
depth(노드 깊이 리스트)
parent(노드 조상(부모 노드) 리스트)
visit(방문 저장 리스트)
BFS(node):
큐에 출발 노드 삽입
visit 방문 처리
level(트리 깊이)
nowSize(현재 깊이에서 트리 크기)
count(카운트)
while 큐가 빌 때까지:
큐에서 노드 데이터 꺼내기
for 현재 노드와 연결된 노드:
if 미 방문 노드:
큐에 데이터 삽입
visit 방문 처리
parent 리스트에 부모 노드 저장
depth 리스트에 깊이 저장
count 1 증가
if nowSize == count: # 현재 깊이의 모든 노드를 방문
count 초기화
nowSize에 바로 아래 단계 트리 노드 개수 저장
level 1 증가
BFS(1)
LCA(노드1, 노드2):
1번 노드가 depth가 더 작으면 1번 노드와 2번 노드 swap
두 노드의 depth를 동일하게 맞추기(a를 부모 노드로 변경을 높이가 맞을 때까지 반복)
두 노드의 같은 조상이 나올 때까지 각 노드를 부모 노드로 변경하는 작업 반복
최소 공통 조상 리턴
m(질의 개수)
for m 반복:
a(1번 노드), b(2번 노드)
print(LCA(a, b))import sys
from collections import deque
input = sys.stdin.readline
print = sys.stdout.write
n = int(input())
tree = [[] for _ in range(n + 1)]
for _ in range(n - 1):
s, e = map(int, input().split())
tree[s].append(e)
tree[e].append(s)
depth = [0] * (n + 1)
parent = [0] * (n + 1)
visit = [False] * (n + 1)
def BFS(node):
qu = deque()
qu.append(node)
visit[node] = True
level = 1
nowSize = 1 # 현재 depth(level) 크기
count = 0 # 현재 depth 에서 몇 개 노드를 처리했는지 알려주는 변수
while qu:
nowNode = qu.popleft()
for next in tree[nowNode]:
if not visit[next]:
visit[next] = True
qu.append(next)
parent[next] = nowNode # 부모 노드 저장
depth[next] = level # 노드 깊이 저장
count += 1
if count == nowSize: # 다음 깊이로 가기 위한 처리
count = 0
nowSize = len(qu)
level += 1
BFS(1)
def LCA(a, b):
if depth[a] < depth[b]: # 무조건 a의 depth를 더 깊게 하기 위해
a, b = b, a # a, b swap - 파이썬 문법
while depth[a] != depth[b]: # depth 맞추기
a = parent[a]
while a != b: # 공통 조상 찾기
a = parent[a]
b = parent[b]
return a # a와 b가 같아졌으니 둘 중 아무거나 리턴
m = int(input())
result = []
for _ in range(m):
a, b = map(int, input().split())
result.append(str(LCA(a, b)))
print("\n".join(result))import javax.swing.*;
import java.io.*;
import java.util.*;
public class Main {
static boolean[] visit;
static ArrayList<Integer>[] tree;
static int[] depth;
static int[] parent;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int n = Integer.parseInt(br.readLine());
visit = new boolean[n + 1];
parent = new int[n + 1];
depth = new int[n + 1];
tree = new ArrayList[n + 1];
for (int i = 1; i < n + 1; i++) {
tree[i] = new ArrayList<>();
}
for (int i = 0; i < n - 1; i++) {
st = new StringTokenizer(br.readLine());
int s = Integer.parseInt(st.nextToken());
int e = Integer.parseInt(st.nextToken());
tree[s].add(e);
tree[e].add(s);
}
BFS(1);
// DFS(1, 0);
StringBuilder sb = new StringBuilder();
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());
sb.append(LCA(a, b)).append("\n");
}
System.out.print(sb);
}
private static int LCA(int a, int b) {
if (depth[a] < depth[b]) {
int temp = a;
a = b;
b = temp;
}
while (depth[a] != depth[b]) {
a = parent[a];
}
while (a != b) {
a = parent[a];
b = parent[b];
}
return a;
}
private static void BFS(int node) {
Queue<Integer> qu = new LinkedList<>();
qu.offer(node);
visit[node] = true;
int level = 1;
int nowSize = 1;
int count = 0;
while (!qu.isEmpty()) {
int nowNode = qu.poll();
for (int next : tree[nowNode]) {
if (!visit[next]) {
visit[next] = true;
qu.offer(next);
parent[next] = nowNode;
depth[next] = level;
}
}
count++;
if (count == nowSize) {
count = 0;
nowSize = qu.size();
level++;
}
}
}
private static void DFS(int node, int level) {
visit[node] = true;
depth[node] = level;
for (int next : tree[node]) {
if (!visit[next]) {
parent[next] = node;
DFS(next, level + 1);
}
}
}
}