題目鏈接:http://poj.org/problem?id=2186
題目大意是有n只牛,如果a受到b的歡迎,b受到c的歡迎,那麼a就會受到c的歡迎,即歡迎是傳遞的。那麼問有幾頭牛是受到其他所有牛的歡迎。
首先需要把相互受歡迎即強連通的牛縮成一個點,即當作一隻牛,如果我們假定邊的指向a->b表示a受到b的歡迎,那麼滿足條件的前提是入度爲0的點一定只能有一個,如果有多個就說明每隻牛都不可能受到所有牛的歡迎,接着這個入度爲0的頂點包含的牛的數量就是要求的牛的數量。如果你邊的定義是相反的,那麼計算的就是出度。所以我的邊都是反向加入的。
代碼:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <iostream>
using namespace std;
const int maxn = 10005;
int ans = 0;
struct E {
int to, next;
} edge[maxn*5];
int head[maxn];
int vis[maxn];
int dfn[maxn];
int low[maxn];
int belong[maxn];
bool instack[maxn];
int Stack[maxn];
int indeg[maxn];
int deep[maxn];
int index = 0, cnt = 0, top = 0;
int n, m;
inline void addEdge(int eid, int from, int to) {
edge[eid].to = to;
edge[eid].next = head[from];
head[from] = eid;
}
void targan(int v) {
dfn[v] = low[v] = ++index;
Stack[++top] = v;
instack[v] = true;
for (int i = head[v]; ~i; i = edge[i].next) {
int u = edge[i].to;
if(!dfn[u]) {
targan(u);
low[v] = min(low[v], low[u]);
}
else if(instack[u]) {
low[v] = min(low[v], dfn[u]);
}
}
if(dfn[v] == low[v]) {
int k;
cnt ++;
deep[cnt] = 0;
do {
k = Stack[top--];
belong[k] = cnt;
instack[k] = false;
deep[cnt] ++;
} while(k != v);
}
}
void suo() {
for(int i = 1; i <= n; i ++) {
for (int j = head[i]; ~j; j = edge[j].next) {
int to = edge[j].to;
if(belong[i] != belong[to]) {
indeg[belong[to]] ++;
}
}
}
}
void getAns() {
int ans = 0, flag = 0;
for(int i = 1; i <= cnt; i ++) {
if(flag == 1 && indeg[i] == 0) {
printf("0\n");
return ;
}
if(indeg[i] == 0) {
ans = deep[cnt];
flag = 1;
}
}
printf("%d\n", ans);
}
void solve() {
memset(dfn, 0, sizeof(dfn));
for (int i = 1; i <= n; i ++) {
if(!dfn[i]) {
targan(i);
}
}
suo();
getAns();
}
int main() {
int x ,y;
// freopen("1.in", "r", stdin);
while (scanf("%d%d", &n, &m) != EOF) {
ans = 0;
memset(head, -1, sizeof(head));
for (int i = 0; i < m; i ++) {
scanf("%d%d", &x, &y);
addEdge(i, y, x);
}
solve();
}
return 0;
}