페이지

11438번: LCA 2

https://www.acmicpc.net/problem/11438


$O(n+m\lg n)$

LCA를 구현하자. sparse table을 이용한다.


#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
const int MAX_N = 100000, LGN = 16;
int n, m;
int dp[MAX_N + 1][LGN + 1], lv[MAX_N + 1];
bool ck[MAX_N + 1];
vector<int> adj[MAX_N + 1];
void dfs(int h) {
    ck[h] = true;
    for (auto it : adj[h]) {
        if (ck[it]) continue;
        lv[it] = lv[h] + 1;
        dp[it][0] = h;
        for (int i = 1; i <= LGN; i++)
            dp[it][i] = dp[dp[it][i - 1]][i - 1];
        dfs(it);
    }
}
int lca(int x, int y) {
    if (lv[x] < lv[y]) swap(x, y);
    for (int i = LGN; i >= 0; i--)
        if (1 << i <= lv[x] - lv[y]) x = dp[x][i];
    if (x == y) return x;
    for (int i = LGN; i >= 0; i--)
        if (dp[x][i] != dp[y][i])
            x = dp[x][i], y = dp[y][i];
    return dp[x][0];
}
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n - 1; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    dfs(1);
    scanf("%d", &m);
    for (int i = 0; i < m; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        printf("%d\n", lca(a, b));
    }
    return 0;
}

댓글 2개 :

  1. dfs 만드는 것 까진 이해했고, lca에서 같은 depth 찾아가는 것 까진 이해했는데 lca 마지막 부분에
    for (int i = LGN; i >= 0; i--)
    if (dp[x][i] != dp[y][i])
    x = dp[x][i], y = dp[y][i];
    return dp[x][0];
    이부분말인데,
    같은 깊이의 x,y 노드에 대해서 2^i 번째 부모가 다르다면 그 밑에 있는 부모는 무조건 lca 가 안 된다는 가정 하에 진행되는 것 같은데...
    이 부분을 증명해줄 수 있을까?

    답글삭제
  2. 이 알고리즘은 트리에서 작동하기 때문에 x가 공통조상이라면 x의 조상노드들은 모두 공통조상임. x가 공통조상이 아닐 때 하위 노드들 중 공통 조상이 존재한다면 x역시 공통 조상이어야 하므로 모순이 생김. 따라서 해당 노드의 하위노드들 중엔 공통조상이 없다는 것을 알 수 있음.

    답글삭제