- 루트 노드를 기준으로 DFS를 통해 각 노드의 트리 높이와 부모 노드를 저장해준다.
- 두 노드의 높이를 맞춰준다.
- 부모노드가 일치할 때까지 각 노드의 부모노드로 이동시켜 준다.
DP[a][b] : a노드에서 2^b번째 부모노드
public static int getMaxIndex() {
return (int)Math.ceil(Math.log(N) / Math.log(2)) + 1;
}
public static void init(int ind, int h, int before) {
depth[ind] = h;
for (int i = 0; i < map.get(ind).size(); i++) {
int next = map.get(ind).get(i);
if (next == before) continue;
dp[next][0] = ind; //다음 노드의 부모 노드를 현재 노드로 지정
init(next, h+1, ind);
}
}
DP[index][a] = DP[DP[index][a-1]][a-1]
이라는 점화식이 도출된다. public static void fillDp() {
for (int i = 1; i < maxInd; i++) {
for (int ind = 1; ind <= N; ind++)
dp[ind][i] = dp[dp[ind][i-1]][i-1];
}
}
- 두 노드의 높이 맞춰주기
- 두 노드를 최소 공통 조상 자식 노드들까지 동시에 업데이트시킨다.
- 각 노드의 부모노드가 최소 공통 조상 노드가 된다.
public static int LCA(int a, int b) {
//ah > bh로 세팅하기
if (depth[a] < depth[b]) {
int tmp = a;
a = b;
b = tmp;
}
//1. 높이 맞춰주기
for (int i = maxInd-1; i >= 0; i--) {
if (Math.pow(2, i) <= depth[a] - depth[b])
a = dp[a][i];
}
if (a==b) return a;
for (int i = maxInd-1; i >= 0; i--) {
if (dp[a][i] == dp[b][i]) continue;
a = dp[a][i];
b = dp[b][i];
}
return dp[a][0];
}