LCA的四种实现方式
1.倍增+\(\rm dfn\)序
int ask(int u, int v)
{
if (dfn[u] > dfn[v]) swap(u, v);
if (u == v) return u;
for (register int i = t; i >= 0; i -- )
if (dfn[fa[v][i]] > dfn[u])
v = fa[v][i];
return fa[v][0];
}
2.树剖(通常是最快的,建议使用)
void dfs(int x, int f)
{
dep[x] = dep[f] + 1; sz[x] = 1; fa[x] = f;
for (auto y : g[x])
{
if (y == f) continue; dfs(y, x);
sz[x] += sz[y]; if (sz[y] > sz[mxs[x]]) mxs[x] = y;
}
return;
}
void rdfs(int x, int tp)
{
top[x] = tp; if (mxs[x]) rdfs(mxs[x], tp);
for (auto y : g[x]) if (y != fa[x] && y != mxs[x]) rdfs(y, y);
return;
}
int lca(int x, int y)
{
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y); return x;
}
3.\(\rm ST\)表(实际效果并不尽人意,不建议使用)
void dfs(int x, int f)
{
p[ ++ ind] = x; dfn[x] = ind; dep[x] = dep[f] + 1;
for (auto y : g[x]) if (y != f) dfs(y, x), p[ ++ ind] = x;
return;
}
void init()
{
rep(i, 1, ind) mn[i][0] = p[i];
rep(j, 1, 20) rep(i, 1, ind - (1 << j))
{
if (dep[mn[i][j - 1]] < dep[mn[i + (1 << (j - 1))][j - 1]]) mn[i][j] = mn[i][j - 1];
else mn[i][j] = mn[i + (1 << (j - 1))][j - 1];
}
lg[0] = -1; rep(i, 1, ind) lg[i] = lg[i >> 1] + 1;
return;
}
int lca(int x, int y)
{
if (dfn[x] > dfn[y]) swap(x, y); int k = lg[dfn[y] - dfn[x] + 1];
if (dep[mn[dfn[x]][k]] < dep[mn[dfn[y] - (1 << k) + 1][k]]) return mn[dfn[x]][k];
else return mn[dfn[y] - (1 << k) + 1][k];
}
4.\(\rm Tarjan\)(数据范围大时,不要用vector
!!!)https://www.luogu.com.cn/blog/Carsonn/solution-p3379