constint N = 10010, M = 50010; int h[N], e[M], ne[M], idx; int dfn[N], sz[N], low[N], timestamp; int id[N], dout[N], scc_cnt; stack<int> stk; bool instk[N]; int n, m;
voidtarjan(int u){ stk.push(u); instk[u] = true; dfn[u] = low[u] = ++timestamp; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (dfn[j] == 0){ tarjan(j); low[u] = min(low[u], low[j]); } elseif (instk[j]) { low[u] = min(low[u], dfn[j]); } } if (dfn[u] == low[u]) { int y; ++scc_cnt; do { y = stk.top(); stk.pop(); instk[y] = false; id[y] = scc_cnt; sz[scc_cnt]++; } while (y != u); } }
voidadd(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
intmain(){ memset(h, -1, sizeof h); cin >> n >> m; for (int i = 0; i < m; i++) { int a, b; cin >> a >> b; add(a, b); } for (int i = 1; i <= n; i++) if (dfn[i] == 0) tarjan(i); // 对强连通分量建图 这里只统计了出度 for (int i = 1; i <= n; i++) for (int j = h[i]; ~j; j = ne[j]) { int k = e[j]; int a = id[i], b = id[k]; if (a != b) dout[a]++; } // 按照拓扑序从后向前遍历所有强连通分量 int zeros = 0, ans = 0; for (int i = 1; i <= scc_cnt; i++) if (dout[i] == 0) { if (++zeros > 1) { ans = 0; break; } ans = sz[i]; } cout << ans << endl; return0; }
学校网络(强连通分量)
一些学校连接在一个计算机网络上,学校之间存在软件支援协议,每个学校都有它应支援的学校名单(学校 A 支援学校 B,并不表示学校 B 一定要支援学校 A)。
constint N = 110, M = 10010; int n; int h[N], e[M], ne[M], idx; int dfn[N], low[N], timestamp, id[N], dout[N], din[N], scc_cnt; stack<int> stk; bool instk[N];
voidadd(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
voidtarjan(int u){ stk.push(u); instk[u] = true; low[u] = dfn[u] = ++timestamp; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (!dfn[j]) tarjan(j), low[u] = min(low[u], low[j]); elseif (instk[j]) low[u] = min(low[u], dfn[j]); } if (low[u] == dfn[u]) { int y; ++scc_cnt; do { y = stk.top(); stk.pop(); instk[y] = false; id[y] = scc_cnt; } while (y != u); } }
intmain(){ cin >> n; memset(h, -1, sizeof h); for (int i = 1; i <= n; i++) { int j; while (cin >> j, j) { add(i, j); } } for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i); for (int i = 1; i <= n; i++) for (int j = h[i]; ~j; j = ne[j]) { int k = e[j]; int a = id[i], b = id[k]; if (a != b) din[b]++, dout[a]++; } int p = 0, q = 0; for (int i = 1; i <= scc_cnt; i++) { if (din[i] == 0) p++; if (dout[i] == 0) q++; } cout << p << endl; if (scc_cnt == 1) cout << 0 << endl; else cout << max(p, q) << endl; return0; }
constint N = 5010, M = 20010; int n, m; int h[N], e[M], ne[M], idx; int low[N], dfn[N], id[N], d[N], timestamp, dcc_cnt; bool bridge[M]; stack<int> stk;
voidadd(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
voidtarjan(int u, int from){ dfn[u] = low[u] = ++timestamp; stk.push(u); for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (!dfn[j]) { tarjan(j, i); low[u] = min(low[u], low[j]); if (low[j] > dfn[u]) bridge[i] = bridge[i^1] = true; } elseif (i != (from ^ 1)) low[u] = min(low[u], dfn[j]); } if (dfn[u] == low[u]) { ++dcc_cnt; int y; do { y = stk.top(); stk.pop(); id[y] = dcc_cnt; } while (y != u); } }
intmain(){ memset(h, -1, sizeof h); cin >> n >> m; for (int i = 0; i < m; i++) { int a, b; cin >> a >> b; add(a, b), add(b, a); } // 缩点 for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i, -1); for (int i = 0; i < idx; i++) if (bridge[i]) d[id[e[i]]]++; int leaf = 0; for (int i = 1; i <= dcc_cnt; i++) if (d[i] == 1) leaf++; cout << (leaf+1)/2 << endl; return0; }
constint N = 10010, M = 30010; int n, m; int h[N], e[M], ne[M], idx; int dfn[N], low[N], timestamp;
int root, s;
voidadd(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
voidtarjan(int u, int from){ dfn[u] = low[u] = ++timestamp; int cnt = 0; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (!dfn[j]) { tarjan(j, i); // 我一开始漏了这句 low[u] = min(low[u], low[j]); if (low[j] >= dfn[u]) cnt++; } elseif (i != (from ^ 1)) { low[u] = min(low[u], dfn[j]); } } if (u != root && cnt > 0) ++cnt; s = max(s, cnt); }
intmain(){ while (cin >> n >> m, n || m) { memset(h, -1, sizeof h); memset(dfn, 0, sizeof dfn); memset(low, 0, sizeof low); idx = 0, s = 0, timestamp = 0; for (int i = 0; i < m; i++) { int a, b; cin >> a >> b; add(a, b), add(b, a); } int cnt = 0; for (root = 0; root < n; root++) if (!dfn[root]) tarjan(root, -1), cnt++; cout << s + cnt - 1 << endl; } return0; }