有向图的强连通分量
在求有向图的强连通分量的时候,有一个特别重要的东西要记住:
有向图和无向图的low函数的意义是不同的。
有向图中,low所指,只能连回当前scc中的点,这也决定了这一行:
else if (!sccno[v]) { lowu = min(lowu, dfn[v]); }
判断scc是否已经找到的因素是,low[u] == dfn[u]这也意味着u是当前scc的第一个发现的点。
sccno初始化为0.
#include <cstdio> #include <cstring> #include <algorithm> #include <stack> using namespace std; const int maxn = 105, maxm = maxn * maxn; stack <int> s; int n, m, tot, dfs_clock, scc_cnt; int h[maxn], dfn[maxn], low[maxn], sccno[maxn]; struct edge { int v, next; }a[maxm]; void add(int x, int y) { a[tot].v = y; a[tot].next = h[x]; h[x] = tot++; } int dfs(int u, int fa) { s.push(u); int lowu = dfn[u] = ++dfs_clock; for (int i = h[u]; ~i; i = a[i].next) { int v = a[i].v; if (!dfn[v]) { int lowv = dfs(v, u); lowu = min(lowu, lowv); }else if (!sccno[v]) { lowu = min(lowu, dfn[v]); } } if (lowu == dfn[u]) { scc_cnt++; for(;;) { int x = s.top(); s.pop(); sccno[x] = scc_cnt; if (x == u) break; } } low[u] = lowu; return lowu; } int main() { freopen("有向图的强连通分量.in","r",stdin); scanf("%d%d", &n, &m); memset(h, -1, sizeof h); tot = dfs_clock = scc_cnt = 0; for (int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); add(x, y); } for (int i = 1; i <= n; i++) if (!dfn[i]) { dfs(i, 0); } for (int i = 1; i <= scc_cnt; i++) { for (int j = 1; j <= n; j++) if (sccno[j] == i) printf("%d ", j); printf("\n"); } return 0; }