Popular Cows
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 30842 Accepted: 12529
Description
Every cow’s dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive, if A thinks B is popular and B thinks C is popular, then A will also think that C is
popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow.
Input
Line 1: Two space-separated integers, N and M
Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.
OutputLine 1: A single integer that is the number of cows who are considered popular by every other cow.
Sample Input
3 3
1 2
2 1
2 3
Sample Output
1
Hint
Cow 3 is the only cow of high popularity.
Source
USACO 2003 Fall
//http://poj.org/problem?id=2186
//先对原图G进行dfs搜索,得到各个点搜索完成的顺序,之后对逆图H进行dfs搜索,从最晚完成搜索的点开始,删除记录能够遍历到的点,这些点构成一个强连通分量.得到所有强连通分量后,把他们各自抽象成一个点,形成一个有向无环图,在该图上寻找出度为0的点.如果仅有一个出度为0的点,则该点被所有点指向,答案为该强连通分量的大小.如果有多个出度为0的点,则这些点无法互相可达,无解,答案为0.
//有向无环图(DAG)保证至少存在一个出度为0的点.
#include <stdio.h>
#include <string>
#include <cstring>
#include <queue>
#include <algorithm>
#include <functional>
#include <vector>
#include <iomanip>
#include <math.h>
#include <iostream>
#include <sstream>
#include <stack>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
const int MAX=10005;
int N,M,a,b,Cnt;
int Num[MAX],Tree[MAX],OutDgree[MAX];
vector<int> G[MAX],H[MAX],F;
bool Mark1[MAX],Mark2[MAX];
void dfs1(int x)
{
Mark1[x]=true;
for (int i=0; i<(int)G[x].size(); i++)
if (!Mark1[G[x][i]])
dfs1(G[x][i]);
F.push_back(x);
}
void dfs2(int x)
{
Mark2[x]=true;
Num[x]=Cnt; //点x的连通分量编号为Cnt
Tree[Cnt]+=1; //编号为Cnt的连通分量大小+1
for (int i=0; i<(int)H[x].size(); i++)
if (!Mark2[H[x][i]])
dfs2(H[x][i]);
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
while (cin>>N>>M)
{
memset(Mark1,false,sizeof(Mark1));
memset(Mark2,false,sizeof(Mark2));
memset(Num,0,sizeof(Num));
memset(Tree,0,sizeof(Tree));
memset(OutDgree,0,sizeof(OutDgree));
Cnt=0;
F.clear();
for (int i=0; i<MAX; i++)
{
G[i].clear();
H[i].clear();
}
for (int i=0; i<M; i++)
{
cin>>a>>b;
G[a].push_back(b);
H[b].push_back(a);
}
for (int i=1; i<=N; i++)
{
if (!Mark1[i])
dfs1(i);
}
for (int i=(int)F.size()-1; i>=0; i--)
{
if (!Mark2[F[i]])
{
Cnt++;
dfs2(F[i]);
}
}
for (int i=1;i<=N;i++)
{
for (int j=0;j<(int)G[i].size();j++)
{
if (Num[i]!=Num[G[i][j]])
OutDgree[Num[i]]+=1;
}
}
int temp=0,Ans=0;
for (int i=1;i<=Cnt;i++)
{
if (!OutDgree[i])
temp++,Ans=i;
}
cout<<(temp>1?0:Tree[Ans])<<endl;
}
return 0;
}