题目:https://vjudge.net/problem/POJ-2186
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
* Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.
Output
Sample Input
3 3 1 2 2 1 2 3
Sample Output
1
Hint
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<algorithm>
#include<map>
#define maxn 200005
using namespace std;
bool used[maxn]; //点是否被遍历
int n,m; //顶点数和边数
vector<int>mp[50005]; //建图数组
vector<int>mp2[50005]; //反向边建立图
vector<int>vs; //后序遍历顺序的顶点列表
int cmp[maxn]; //强连通分量的拓扑序
//建立图
void add_edge(int from,int to)
{
mp[from].push_back(to); //正反建立图
mp2[to].push_back(from);
}
//第一次dfs遍历
void dfs(int x)
{
used[x]=true; // 标记
for(int i=0;i<mp[x].size();i++)
{
if(!used[mp[x][i]])dfs(mp[x][i]); //dfs图
}
//cout<<x<<endl;
vs.push_back(x); //记录遍历的顺序
}
//第二次dfs遍历
void rdfs(int x,int k)
{
used[x]=true; //标记点
cmp[x] = k; //记录属于一个集合
for(int i = 0; i<mp2[x].size(); i ++)
{
if(!used[mp2[x][i]])rdfs(mp2[x][i],k);
}
}
//查询模板 计算强连通图的个数
int scc()
{
memset(used,false,sizeof(used));
vs.clear();
for(int i = 0;i < n;i ++)
{
if(!used[i])dfs(i);
}
memset(used,false,sizeof(used));
int k=0;
for(int i=vs.size()-1;i>=0;i--) //从查询顺序和第一次查询顺序相反
{
if(!used[vs[i]])rdfs(vs[i],k++);
}
return k;
}
int a[maxn],b[maxn];
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
cin>>a[i]>>b[i];
add_edge(a[i]-1,b[i]-1);
}
int ans=scc();
int flag=0;
int num=0;
//cout<<ans<<endl;
for(int i=0;i<n;i++)
{
if(cmp[i]==ans-1)
{
flag=i;
num++;
}
}
// cout<<flag<<endl;
//cout<<num<<endl;
//检查是否从所有点可达
memset(used,false,sizeof(used));
rdfs(flag,0); //重新用强连通分量分解的代码
for(int i=0;i<n;i++)
{
if(!used[i]){
num=0;
break;
}
}
cout<<num<<endl;
return 0;
}
/*
12 16
2 3
3 2
4 3
4 1
5 7
6 3
6 4
6 5
7 6
8 10
9 8
9 7
10 9
11 8
11 10
12 11
0
*/