Tarjan 的一些板子

圆方树(会在两圆点间建方点):

void tarjan(int u)
{
	low[u] = dfn[u] = ++dfc, stk[++top] = u, num++;
	for (int v : G[u]) if (!dfn[v])
	{
		tarjan(v), low[u] = std::min(low[u], low[v]);
		if (low[v] == dfn[u])
		{
			++ncr; for (int x = 0; x != v; --top)
			{
				x = stk[top], T[ncr].push_back(x), T[x].push_back(ncr), val[ncr]++;
			}
			T[ncr].push_back(u), T[u].push_back(ncr), val[ncr]++;
		}
	}
	else low[u] = std::min(low[u], dfn[v]);
}

仙人掌(不建的版本):

inline void calc(int u, int v, int val)
{
	ncr++; int tmp = val, i = v; while (i != fa[u])
	{
		sum[i] = tmp, tmp += res[i], i = fa[i];
	}
	sum[ncr + n] = sum[u], i = v, sum[u] = 0; while (i != fa[u])
	{
		tmp = min(sum[i], sum[ncr + n] - sum[i]);
		T[ncr + n].insert(T[ncr + n].begin(), Edge { i, tmp });
		T[i].insert(T[i].begin(), Edge { ncr + n, tmp }); i = fa[i];
	}
}

void Tarjan(int u, int f)
{
	dfn[u] = low[u] = ++dfc; for (Edge v : G[u])
	{
		if (!dfn[v.to])
		{
			fa[v.to] = u, res[v.to] = v.vl, Tarjan(v.to, u), low[u] = min(low[u], low[v.to]);
		}
		else if (v.to != f) low[u] = min(low[u], dfn[v.to]);
		if (low[v.to] > dfn[u]) T[u].push_back(v), T[v.to].push_back(Edge{ u, v.vl });
	}
	for (Edge v : G[u]) if (fa[v.to] != u && dfn[v.to] > dfn[u]) calc(u, v.to, v.vl);
}

posted @ 2021-01-08 11:28  Linshey  阅读(113)  评论(0编辑  收藏  举报