崇拜有传递性。求所有牛都崇拜的牛
tarjan算法求强连通。
如果不连通就不存在。如果联通,缩点后唯一一个出度为零的点就是答案,有多个则不存在。
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <complex> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> #include <ctime> #include <cassert> using namespace std; const int N = 10005; const int M = 100005; struct Edge { int to, next; } edge[M]; int head[N]; int cnt_edge; void add_edge(int u, int v) { edge[cnt_edge].to = v; edge[cnt_edge].next = head[u]; head[u] = cnt_edge; cnt_edge++; } int dfn[N]; int low[N]; int stk[N]; bool in[N]; int kind[N]; int top; int idx; int cnt; int n, m; void dfs(int u) { dfn[u] = low[u] = ++idx; in[u] = true; stk[++top] = u; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (!dfn[v]) { dfs(v); low[u] = min(low[v], low[u]); } else if(in[v]) { low[u] = min(low[u], dfn[v]); } } if (low[u] == dfn[u]) { ++cnt; int j; do { j = stk[top--]; in[j] = false; kind[j] = cnt; } while (j != u); } } void init() { memset(dfn, 0, sizeof dfn); memset(head, -1, sizeof head); cnt_edge = 0; top = cnt = idx = 0; } int deg[N]; void solve() { // 缩点后出度为0的点个数为1 for (int u = 1; u <= n; ++u) { int k = kind[u]; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (kind[u] != kind[v]) deg[k]++; } } int flag = 0; int p; for (int i = 1; i <= cnt; ++i) { if (deg[i] == 0) { flag++; p = i; if (flag > 1) break; } } if (flag == 1) { int ans = 0; for (int i = 1; i <= n; ++i) if (kind[i] == p) ++ans; printf("%d ", ans); } else { printf("0 "); } } int main() { while (~scanf("%d%d", &n, &m)) { if (n == 0 && m == 0) break; int a, b; init(); for (int i = 0; i < m; ++i) { scanf("%d%d", &a, &b); add_edge(a, b); } for (int i = 1; i <= n; ++i) { if (!dfn[i]) dfs(i); } solve(); } return 0; }