受欢迎的牛(popular)
Description
原题来自:USACO 2003 Fall
每一头牛的愿望就是变成一头最受欢迎的牛。现在有 N 头牛,给你 M 对整数 (A,B),表示牛 A 认为牛 B 受欢迎。这种关系是具有传递性的,如果 A 认为 B 受欢迎,B 认为 C 受欢迎,那么牛 A 也认为牛 C 受欢迎。你的任务是求出有多少头牛被除自己之外的所有牛认为是受欢迎的。
Input
第一行两个数 N,M;
接下来 M 行,每行两个数 A,B,意思是 A 认为 B 是受欢迎的(给出的信息有可能重复,即有可能出现多个 A,B)。
Output
输出被除自己之外的所有牛认为是受欢迎的牛的数量。
Sample Input 1
3 3
1 2
2 1
2 3
Sample Output 1
1
Hint
样例说明
只有第三头牛被除自己之外的所有牛认为是受欢迎的。
数据范围:
对于全部数据,1≤N≤10,000;1≤M≤50,000
题目大意:
找出被除自己以外所有牛欢迎的牛,典型的强连通分量,找出所有的强连通分量,然后进行压点,如果想满足题目要求,就必须让所有点中出度为0的点有且仅有一个。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+5;
int low[maxn],instack[maxn],dfn[maxn];
int Stack[maxn],in[maxn],t[maxn],tt[maxn];
int tot,num,cnt;
int n,m;
struct node
{
int v;
node(int vv):v(vv){}
};
vector<node>e[maxn];
void add_edge(int u , int v)
{
e[u].push_back(node(v));
}
void tarjan(int u)
{
dfn[u] = low[u] = ++tot;
Stack[++num] = u;
instack[u] = 1;
for(int i = 0 ; i < e[u].size() ; i++)
{
int v = e[u][i].v;
if(dfn[v] == 0)
{
tarjan(v);
low[u] = min(low[u],low[v]);
}
else if(instack[v])
{
low[u] = min(low[u],dfn[v]);
}
}
if(dfn[u] == low[u])
{
while(u != Stack[num])
{
t[Stack[num]] = cnt;
tt[cnt]++;
instack[Stack[num]] = 0;
num--;
}
t[Stack[num]] = cnt;
tt[cnt]++;
instack[Stack[num]] = 0;
num--;
cnt++;
}
}
int main()
{
cin >> n >> m;
for(int i = 0 ; i < m ; i++)
{
int u,v;
cin >> u >> v;
add_edge(u,v);
}
for(int i = 1 ; i <= n ; i++)
{
if(!dfn[i])
tarjan(i);
}
int sum = 0;
for(int i = 1 ; i <= n ; i++)
{
for(int j = 0 ; j < e[i].size() ; j++)
{
int v = e[i][j].v;
if(t[i] != t[v])
in[t[i]]++;
}
}
int flag = 0;
for(int i = 0 ; i < cnt ; i++)
{
if(!in[i])
{
flag++;
sum = tt[i];
}
}
if(flag == 1)
cout << sum << endl;
else
cout << "0" << endl;
return 0;
}