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);
}
as 0.4123