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

posted @ 2020-10-28 21:23  andysj  阅读(114)  评论(1编辑  收藏  举报