int dfn[maxn]; //第i个点被dfs到次序
int low[maxn]; //二叉搜索树上i所在子数上仍在栈中的最小dfn,low[i]相等的点在一个强连通分量中
bool vis_tarjan[maxn];
stack<int>s_tarjan;
int tot_tarjan;
int cnt_tarjan;
int res_tarjan[maxn]; //储存强连通分量,res[i]表示点i属于第res[i]个强连通分量
int num_tarjan[maxn]; //第i个强连通分量的点数
void tarjan(int x)
{
dfn[x] = low[x] = ++cnt_tarjan;
s_tarjan.push(x);
vis_tarjan[x] = true;
for (int i = head[x]; ~i; i = e[i].nxt)
{
int v = e[i].v;
if (!dfn[v])
{
tarjan(v);
low[x] = min(low[x], low[v]);
}
else if (vis_tarjan[v])
{
low[x] = min(low[x], dfn[v]);
}
}
if (low[x] == dfn[x])
{
tot_tarjan++;
while (!s_tarjan.empty() && s_tarjan.top() != x)
{
int t = s_tarjan.top();
res_tarjan[t] = tot_tarjan;
num_tarjan[tot_tarjan]++;
vis_tarjan[t] = false;
s_tarjan.pop();
};
s_tarjan.pop();
res_tarjan[x] = tot_tarjan;
num_tarjan[tot_tarjan]++;
vis_tarjan[x] = false;
}
}