http://poj.org/problem?id=2186
首先求出所有的强连通分量,分好块。然后对于每一个强连通分量,都标记下他们的出度。那么只有出度是0 的块才有可能是答案,为什么呢?因为既然你有了出度,那么就是指向了另外一个块,那么你就不能指望那个块也指向你了,因为这样会形成环,所以肯定有一个块的cow不支持你,所以你这个块就不会是popular cow
那么就有两种情况,
①、出度是0的块的个数是1个,那么就是唯一的答案。
②、出度是0的快的个数有多个,那么答案是0, 因为至少也有一个块不支持你。
不会存在出度为0的个数是0这样的,起码都会有一个块出度是0.
记得清空各种数组。

#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> #include <bitset> const int maxn = 1e5 + 20; struct Edge { int u, v, w, tonext; }e[maxn * 2]; int first[maxn], num; void addEdge(int u, int v) { ++num; e[num].u = u, e[num].v = v; e[num].tonext = first[u]; first[u] = num; } int DFN[maxn], low[maxn], st[maxn], top, when, vis[maxn]; int id[maxn], toSelId, out[maxn], sum[maxn]; void tarjan(int cur, int fa) { DFN[cur] = low[cur] = ++when; // 时间戳 st[++top] = cur; //进栈 vis[cur] = true; for (int i = first[cur]; i; i = e[i].tonext) { int v = e[i].v; if (!DFN[v]) { //没访问过 tarjan(v, cur); low[cur] = min(low[cur], low[v]); } else if (vis[v]) { // 访问过,而且还在栈里 low[cur] = min(low[cur], DFN[v]); } } if (low[cur] == DFN[cur]) { //这个是强连通分量的根节点。 ++toSelId; do { id[st[top]] = toSelId; sum[toSelId]++; // printf("%d ", st[top]); vis[st[top]] = false; top--; } while (cur != st[top + 1]); // printf(" "); } } void sloveTarjan(int n) { //防止开始枚举的节点没有出边,暴力枚举每一个节点 memset(low, 0, sizeof low); memset(DFN, 0, sizeof DFN); memset(vis, 0, sizeof vis); memset(id, 0, sizeof id); memset(out, 0, sizeof out); memset(sum, 0, sizeof sum); top = when = toSelId = 0; for (int i = 1; i <= n; ++i) { if (!DFN[i]) { tarjan(i, i); } } } int n, m; void work() { // int n, m; // scanf("%d%d", &n, &m); num = 0; memset(first, 0, sizeof first); for (int i = 1; i <= m; ++i) { int u, v; scanf("%d%d", &u, &v); addEdge(u, v); } sloveTarjan(n); for (int i = 1; i <= n; ++i) { for (int j = first[i]; j; j = e[j].tonext) { int v = e[j].v; if (id[i] == id[v]) continue; out[id[i]]++; } } int has = 0; int ans; for (int i = 1; i <= toSelId; ++i) { if (out[i] == 0) { has++; ans = i; } } if (has >= 2) { printf("0 "); // cout << 0 << endl; return; } printf("%d ", sum[ans]); // cout << sum[ans] << endl; } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif while (scanf("%d%d", &n, &m) != EOF) work(); return 0; }