A - Popular Cows POJ - 2186
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.
Output
* Line 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.
给你n个点,m条有向边,问你有多少个点是能从任意点走到的
首先正常强连通缩点,每一个点的强联通标号都存在belong里
遍历每一条边,如果是属于同一个强连通里的,就不管,否则就建边
会得到一个有向无环图,记录此图中所有的点的出度,如果这个图里
有超过两个出度为零的点,就不是连通图,答案为0
否则,就输出度为零的强连通分量里的点数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn=1e4+10;
vector <int> G[maxn];
int dfn[maxn],low[maxn],s[maxn];
int belong[maxn],vis[maxn],out[maxn];
int cnt,num,top;
void dfs(int u)
{
dfn[u]=low[u]=++num;
s[++top]=u;
vis[u]=1;
for(int i=0; i<G[u].size(); i++)
{
int v=G[u][i];
if(!dfn[v])
{
dfs(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]&&dfn[v]<low[u])
low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
cnt++;
int v;
do
{
v=s[top--];
vis[v]=0;
belong[v]=cnt;
} while(v!=u);
}
}
void tarjan(int n)
{
cnt=num=top=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(vis,0,sizeof(vis));
memset(belong,0,sizeof(belong));
memset(out,0,sizeof(out));
for(int i=1; i<=n; i++)
{
if(!dfn[i]) dfs(i);
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
for(int i=1; i<=m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
}
tarjan(n);
for(int u=1; u<=n; u++)
{
for(int i=0; i<G[u].size(); i++)
{
int v=G[u][i];
if(belong[u]==belong[v]) continue; //所点后要是同一个强联通分量里的就不管,不是的建边
else out[belong[u]]++;
}
}
int sum=0,flag;
for(int i=1; i<=cnt; i++)
{
if(out[i]==0)
{
sum++;
flag=i;
}
}
if(sum!=1) printf("0\n");
else
{
int ans=0;
for(int i=1; i<=n; i++)
{
if(belong[i]==flag) ans++;
}
printf("%d\n",ans);
}
}
return 0;
}