_bzoj1051 [HAOI2006]受欢迎的牛【强联通】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1051
保存tarjan模版。
求强联通分量,缩点。
#include <cstdio> #include <cstring> #include <set> #include <algorithm> const int maxn = 10005, maxm = 50005; int n, m, t1, t2; int top[maxn], dfn[maxn], dfs_clock, scc[maxn], scc_cnt, stk[maxn], top_; int head1[maxn], to1[maxm], next1[maxm], lb1; int siz[maxn]; char out[maxn]; inline void ist1(int aa, int ss) { to1[lb1] = ss; next1[lb1] = head1[aa]; head1[aa] = lb1; ++lb1; } void dfs(int r) { dfn[r] = top[r] = ++dfs_clock; stk[top_++] = r; for (int j = head1[r]; j != -1; j = next1[j]) { if (!dfn[to1[j]]) { dfs(to1[j]); top[r] = std::min(top[r], top[to1[j]]); } else if (!scc[to1[j]]) { top[r] = std::min(top[r], dfn[to1[j]]); } } if (dfn[r] == top[r]) { ++scc_cnt; while (stk[top_ - 1] != r) { scc[stk[top_ - 1]] = scc_cnt; --top_; ++siz[scc_cnt]; } scc[r] = scc_cnt; --top_; ++siz[scc_cnt]; } } int main(void) { //freopen("in.txt", "r", stdin); memset(head1, -1, sizeof head1); memset(next1, -1, sizeof next1); scanf("%d%d", &n, &m); while (m--) { scanf("%d%d", &t1, &t2); ist1(t1, t2); } for (int i = 1; i <= n; ++i) { if (!scc[i]) { dfs(i); } } for (int i = 1; i <= n; ++i) { for (int j = head1[i]; j != -1; j = next1[j]) { if (scc[i] != scc[to1[j]]) { out[scc[i]] = 1; } } } char flag = 0; int ans = 0; for (int i = 1; i <= scc_cnt; ++i) { if (!out[i]) { if (flag) { ans = 0; break; } else { flag = 1; ans = siz[i]; } } } printf("%d\n", ans); return 0; }