模板 - 图论 - 树 - 最近公共祖先
Posted yinku
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板 - 图论 - 树 - 最近公共祖先相关的知识,希望对你有一定的参考价值。
令 $f[i][j]$ 表示 $i$ 的 $2^j$ 辈祖先, $f[i][0]$ 就表示 $i$ 的父节点。
可以得到状态转移方程 $f[i][j]=f[f[i][j-1]][j-1]$ 。当没有 $2^j$ 辈祖先时 $f[i][j]=0$
一遍 DFS 计算即可
void dfs(int u, int father) { dep[u] = dep[father] + 1; // dep[x] 表示 x 的深度,在查询时会用到 for (int i = 0; i <= 19; i++) f[u][i + 1] = f[f[u][i]][i]; // 预处理 for (int i = first[u]; i; i = next[i]) {/ 链式前向星 int v = go[i]; if (v == father) continue; f[v][0] = u; // f[v][0] 表示 v 的父亲 dfs(v, u); } }
查询
先往上2进制跳到同深度,再2进制一起往上跳。
int lca(int x, int y) { if (dep[x] < dep[y]) swap(x, y); // 步骤 1 for (int i = 20; i >= 0; i--) { // 步骤 2 if (dep[f[x][i]] >= dep[y]) x = f[x][i]; if (x == y) return x; } for (int i = 20; i >= 0; i--) // 步骤 3 if (f[x][i] != f[y][i]) { x = f[x][i]; y = f[y][i]; } return f[x][0]; }
以上是关于模板 - 图论 - 树 - 最近公共祖先的主要内容,如果未能解决你的问题,请参考以下文章