diff --git a/graph/lca.cc b/graph/lca.cc new file mode 100644 index 0000000..78560bd --- /dev/null +++ b/graph/lca.cc @@ -0,0 +1,48 @@ +struct LCA { + vector depth; + vector> pa; + LCA(const vector>& g, int root = 1) { + int n = g.size() - 1; + int m = 32 - __builtin_clz(n); + depth.resize(n + 1); + pa.resize(n + 1, vector(m, -1)); + function dfs = [&](int x, int fa) { + pa[x][0] = fa; + for (int y: g[x]) { + if (y != fa) { + depth[y] = depth[x] + 1; + dfs(y, x); + } + } + }; + dfs(root, 0); + + for (int i = 0; i < m - 1; i++) + for (int x = 1; x <= n; x++) + if (int p = pa[x][i]; p != -1) + pa[x][i + 1] = pa[p][i]; + } + + int get_kth_ancestor(int node, int k) { + for (; k; k &= k - 1) + node = pa[node][__builtin_ctz(k)]; + return node; + } + + int query(int x, int y) { + if (depth[x] > depth[y]) + swap(x, y); + y = get_kth_ancestor(y, depth[y] - depth[x]); + if (y == x) + return x; + for (int i = pa[x].size() - 1; i >= 0; i--) { + int px = pa[x][i], py = pa[y][i]; + if (px != py) { + x = px; + y = py; + } + } + return pa[x][0]; + } +}; +