有向图的强联通分量
/********************* 缩点 *********************/
struct SCC
{
int n, m; // 点数和边数
vector<vector<int>> G, g; // 原图和新图
vector<int> stk;
vector<int> dfn, low, bel, ind;
vector<PII> edge;
int cur, cnt;
SCC() {}
SCC(int n, int m)
{
init(n, m);
}
void init(int n, int m)
{
this->n = n;
this->m = m;
G.assign(n + 1, {});
dfn.assign(n + 1, -1);
low.resize(n + 1);
bel.assign(n + 1, -1);
edge.resize(m + 1);
stk.clear();
cur = cnt = 1;
}
void addEdge(int u, int v)
{
G[u].push_back(v);
}
void dfs(int x)
{
dfn[x] = low[x] = cur++;
stk.push_back(x);
for (auto y : G[x])
{
if (dfn[y] == -1)
{
dfs(y);
low[x] = min(low[x], low[y]);
}
else if (bel[y] == -1)
{
low[x] = min(low[x], dfn[y]);
}
}
if (dfn[x] == low[x])
{
int y;
do {
y = stk.back();
bel[y] = cnt;
stk.pop_back();
// cout << y << ' ' << cnt << '\n';
} while (y != x);
cnt++;
}
}
// 缩点
void work()
{
for (int i = 1; i <= n; i ++ )
{
if (dfn[i] == -1) dfs(i);
}
}
// 建新图
void build()
{
ind.assign(cnt + 1, 0);
g.resize(cnt + 1);
for (int i = 1; i <= m; i ++ )
{
int a = bel[edge[i].first];
int b = bel[edge[i].second];
if (a != b)
{
g[a].push_back(b);
ind[b] ++ ;
}
}
}
};
/***********************************************/