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("\n");
}
}
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\n");
// cout << 0 << endl;
return;
}
printf("%d\n", 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;
}