【图论】[BZOJ 1051]受欢迎的牛
题目问的是有多少个牛收到所有的牛的喜欢,因为这道题目具有传递性,所以在有向图上找出强连通子图,可以发现每个子图中的奶牛一定是互相喜欢的,所以不用考虑这样的情况(把每一个强连通子图找出,缩点)然后整个图就变成了有向无环图,那么同一个点必须受到其他所有奶牛的喜欢,那么它不能喜欢任意的除了自己这个联通子图的牛的其他牛(会形成环)所以统计一下是否存在出度为0的点就好了,但是如果存在两个或两个以上的出度为0的点,那么这个有向无环图就变成了一个森林(多个独立的有向无环图)
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <stack>
using namespace std;
const int MAXN = 10000;
const int MAXM = 50000;
struct node{
int v;
node *next;
}Edges[MAXM*2+10], *ecnt=Edges, *adj[MAXN+10];
void addedge(int u, int v){
++ecnt;
ecnt->v = v;
ecnt->next = adj[u];
adj[u] = ecnt;
}
int dfn[MAXN+10], low[MAXN+10], dcnt, id[MAXN+10], kcnt, sz[MAXN+10];
bool insta[MAXN+10];
stack<int> sta;
void dfs(int u){
dfn[u] = low[u] = ++dcnt; sta.push(u); insta[u] = true;
for(node *p=adj[u];p;p=p->next){
int v = p->v;
if(!dfn[v]){
dfs(v);
low[u]= min(low[u], low[v]);
}else if(insta[v])
low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u]){
int tmp; ++kcnt;
do{
tmp = sta.top();
id[tmp] = kcnt;
sta.pop();
sz[kcnt]++;
insta[u] = false;
}while(tmp!=u);
}
}
bool ans[MAXN+10];
void solve(){
int n, m, u, v;
scanf("%d%d", &n, &m);
for(int i=1;i<=m;i++){
scanf("%d%d", &u, &v);
addedge(u, v);
}
for(int i=1;i<=n;i++)
if(!dfn[i])
dfs(i);
//printf("%d\n", kcnt);
for(int i=1;i<=n;i++)
for(node *p=adj[i];p;p=p->next)
if(id[p->v] != id[i])
ans[id[i]] = true;
int Print = 0;
for(int i=1;i<=kcnt;i++)
if(!ans[i]){
if(Print){
printf("0\n");
return ;
}
Print = sz[i];
}
printf("%d\n", Print);
}
int main(){
solve();
return 0;
}