const int maxn = 10010;
int dfn[maxn]; //第i个点被dfs到次序
int low[maxn];    //二叉搜索树上i所在子数上仍在栈中的最小dfn,low[i]相等的点在一个强连通分量中
bool vis[maxn];
stack<int>s;
vector<int>to[maxn];
int tot;
int res[maxn];    //储存强连通分量,res[i]表示点i属于第res[i]个强连通分量
int num[maxn];    //第i个强连通分量的点数

void tarjan(int x)
{
    dfn[x] = low[x] = ++cnt;
    s.push(x);
    vis[x] = true;
    for (int i = 0; i < to[x].size(); i++)
    {
        if (!dfn[to[x][i]])
        {
            tarjan(to[x][i]);
            low[x] = min(low[x], low[to[x][i]]);
        }
        else if (vis[to[x][i]])
        {
            low[x] = min(low[x], dfn[to[x][i]]);
        }
    }
    if (low[x] == dfn[x])
    {
        tot++;
        while (!s.empty() && s.top() != x)
        {
            int t = s.top();
            res[t] = tot;
            num[tot]++;
            vis[t] = false;
            s.pop();
        };
        s.pop();
        res[x] = tot;
        num[tot]++;
        vis[x] = false;
    }
}
01-21 07:09