1513:【 例 1】受欢迎的牛
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 808 通过数: 428
【题目描述】
原题来自:USACO 2003 Fall
每一头牛的愿望就是变成一头最受欢迎的牛。现在有 N 头牛,给你 M 对整数 (A,B),表示牛 A 认为牛 B 受欢迎。这种关系是具有传递性的,如果 A 认为 B 受欢迎,B 认为 C 受欢迎,那么牛 A 也认为牛 C 受欢迎。你的任务是求出有多少头牛被除自己之外的所有牛认为是受欢迎的。
【输入】
第一行两个数 N,M;
接下来 M 行,每行两个数 A,B,意思是 A 认为 B 是受欢迎的(给出的信息有可能重复,即有可能出现多个 A,B)。
【输出】
输出被除自己之外的所有牛认为是受欢迎的牛的数量。
【输入样例】
3 3
1 2
2 1
2 3
【输出样例】
1
【提示】
样例说明
只有第三头牛被除自己之外的所有牛认为是受欢迎的。
数据范围:
对于全部数据,1≤N≤104,1≤M≤5×104。
思路:缩点,是否只有一个出度为0的缩点集合。
#include <bits/stdc++.h>
using namespace std;
const int N=5e4+5;
int n,m,dfn[N],vis[N],low[N],t=0,num=0,b[N],cnt[N];
int x[N],y[N],out[N];
vector<int> a[N];
stack<int> s;
void dfs(int x)
{
dfn[x]=low[x]=++t;
s.push(x);
vis[x]=1;
for(int i=0;i<a[x].size();i++)
{
int y=a[x][i];
if(!dfn[y])
{
dfs(y);
low[x]=min(low[x],low[y]);
}
else if(vis[y])
low[x]=min(low[x],low[y]);
}
if(low[x]==dfn[x])
{
num++;
while(s.top()!=x)
{
b[s.top()]=num;//编号
cnt[num]++;
vis[s.top()]=0;
s.pop();
}
b[x]=num;
cnt[num]++;
vis[x]=0;
s.pop();
}
}
int main()
{
scanf("%d%d",&n,&m);
//cin >> n >> m;
for(int i=0;i<m;i++)
{
scanf("%d%d",&x[i],&y[i]);
//cin >> x[i] >> y[i];
a[x[i]].push_back(y[i]);
}
for(int i=1;i<=n;i++)
if(!dfn[i])
dfs(i);
for(int i=0;i<m;i++)//新建图,缩点
{
int x0=b[x[i]],y0=b[y[i]];
if(x0!=y0)
out[x0]++;
}
int res=0,x=0;
for(int i=1;i<=num;i++)
{
if(out[i]==0)
{
x=i;
res++;
}
if(res>1)
{
printf("0\n");
return 0;
}
}
printf("%d\n",cnt[x]);
return 0;
}