p2341&bzoj1051 受欢迎的牛
题目
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
Input
Output
一个数,即有多少头牛被所有的牛认为是受欢迎的。
Sample Input
1 2
2 1
2 3
Sample Output
HINT
分析
首先我们把牛的喜欢关系建图,然后Tarjan缩点同时计算一个环内的点的数量(这个时候就把自己算进去了),重新建图之后我们经过感性思考不难想出如果要让所有牛都喜欢最基本的条件就是出度为零,因为如果有出度就代表这个点指向了别的点,而在一个有向无环图中这就代表了一定有点不指向出度非零的点,但如果有大于一个出度为零的点就代表图是不连通的,所以直接输出零,而如果只有一个出度为零的点,就输出这个点所代表的环所含点的个数
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int dfn[110000],low[110000],star[110000],cnt,sum,belong[110000];
int num[110000],isr[110000];
vector<int>v[110000];
stack<int>a;
stack<int>b;
queue<int>q;
void tarjan(int x){
low[x]=dfn[x]=++cnt;
a.push(x);
isr[x]=1;
int i,j,k;
for(i=0;i<v[x].size();i++)
if(!dfn[v[x][i]]){
tarjan(v[x][i]);
low[x]=min(low[x],low[v[x][i]]);
}else if(isr[x]){
low[x]=min(low[x],dfn[v[x][i]]);
}
if(dfn[x]==low[x]){
int tot=0;
sum++;
while(1){
int u=a.top();
belong[u]=sum;
b.push(u);
tot++;
a.pop();
isr[u]=0;
if(u==x)break;
}
while(!b.empty()){
star[sum]=tot;
b.pop();
}
}
}
int main()
{ int n,m,i,j,k,x,y;
cin>>n>>m;
for(i=1;i<=m;i++){
cin>>x>>y;
v[x].push_back(y);
}
for(i=1;i<=n;i++)
if(!dfn[i])tarjan(i);
for(i=1;i<=n;i++)
for(j=0;j<v[i].size();j++)
if(belong[v[i][j]]!=belong[i]){
num[belong[i]]++;
}
int wh,tot=0;
for(i=1;i<=sum;i++)
if(!num[i]){
tot++;
wh=i;
}
if(tot!=1){
cout<<0<<endl;
return 0;
}
cout<<star[wh]<<endl;
return 0;
}