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; }
typedeflonglong LL; constint N = 100010, M = 1000010; int n, m, h[N], idx = 2; int dfn[N], low[N], ts; structEdge { int to, ne; } e[M]; int root, sz[N]; LL ans[N];
voidadd(int h[], int a, int b){ e[idx] = {b, h[a]}, h[a] = idx++; }
voidtarjan(int u, int fa){ dfn[u] = low[u] = ++ts; bool cut = false; int sons = 0;
sz[u] = 1; // u 下面的连通块 LL sum = 0; for (int i = h[u]; i; i = e[i].ne) { int j = e[i].to; if (!dfn[j]) { tarjan(j, u); low[u] = min(low[u], low[j]); sz[u] += sz[j];
if (low[j] >= dfn[u]) { sum += sz[j]; ans[u] += 1LL * sz[j] * (n - sz[j] - 1);
sons++; if (u != root || sons >= 2) cut = true; } } else low[u] = min(low[u], dfn[j]); }
if (root == u && sons == 0) cut = true;
if (!cut) return ans[u] = (n-1) * 2, void(); ans[u] += (n - sum - 1) * sum + (n-1) * 2; }
intmain(){ scanf("%d%d", &n, &m); for (int i = 0, a, b; i < m; i++) { scanf("%d%d", &a, &b); add(h, a, b), add(h, b, a); }
// 数据保证图连通 root = 1; tarjan(1, 0); for (int u = 1; u <= n; u++) printf("%lld\n", ans[u]); return0; }