题目链接:http://poj.org/problem?id=2186
题目大意:奶牛们又开始得瑟了,他们想知道究竟哪只牛(或者说是多少只。。)在牛们中最知名,如果a觉得b出名,b觉得c出名,那么a也会觉得c出名。。
题目思路:用tarjan求解的,先缩点之后建立一个新图,然后判断出度为零的点是否有且只有一个,如果是的话就输出属于这个强连通分量的点的个数,不是的话就输出零。
AC代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof((a)))
void RI (int& x){
x = 0;
char c = getchar ();
while (c == ' '||c == '\n') c = getchar ();
bool flag = 1;
if (c == '-'){
flag = 0;
c = getchar ();
}
while (c >= '0' && c <= '9'){
x = x * 10 + c - '0';
c = getchar ();
}
if (!flag) x = -x;
}
void RII (int& x, int& y){RI (x), RI (y);}
void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);}
const int maxn = 11000;
const int maxm = 55000;
int n,m;
struct Side{
int u,v,next;
}side[maxm];
int top,node[maxn];
int t,dfn[maxn],low[maxn],sum;
stack<int>s;
void add_side(int u,int v){
side[top] = (Side){u,v,node[u]};
node[u] = top++;
}
void init(){
memset(node,-1,sizeof(node));
memset(dfn,0,sizeof(dfn));
top=sum=t=0;
}
void dfs(int u){
dfn[u]=low[u]=++t;
s.push(u);
for(int i=node[u];i!=-1;i=side[i].next){
int v=side[i].v;
if(!dfn[v])dfs(v);
if(dfn[v]!=-1)low[u]=min(low[u],low[v]);
}
if(low[u]==dfn[u]){
int v;
do{
v=s.top();s.pop();
dfn[v]=-1;
low[v]=sum;
}while(v!=u);
sum++;
}
}
int in[maxn];
void build(){
int tmp = top;
top = 0;
mem(node,-1);
mem(in,0);
for(int i = 0;i < tmp;i ++){
if(low[side[i].u] != low[side[i].v]){
in[low[side[i].v]] ++;
add_side(low[side[i].u],low[side[i].v]);//cout<<low[side[i].u]<<' '<<low[side[i].v]<<endl;
}
}
//for(int i = 0;i < sum;i ++)cout<<in[i]<<' ';cout<<endl;
}
int get(int ss){
int ans = 0;
for(int i = 1;i <= n;i ++){
if(low[i] == ss)ans ++;
}
return ans;
}
int main(){
//freopen("test.txt","r",stdin);
while(~scanf("%d%d",&n,&m)){
init();
while(m --){
int a,b;
RII(a,b);
add_side(b,a);//cout<<b<<' '<<a<<endl;
}
for(int i = 1;i <= n;i ++){
if(!dfn[i])dfs(i);
}
//for(int i = 1;i <= n;i ++)cout<<low[i]<<' ';cout<<endl;
build();
int ss;
int num = 0;
for(int i = 0;i < sum;i ++){
if(in[i] == 0){ss = i;num ++;}
}
if(num > 1)cout<<0<<endl;
else {
cout<<get(ss)<<endl;
}
}
return 0;
}