bzoj1051 受欢迎的牛

Description

  每一头牛的愿望就是变成一头最受欢迎的牛。现在有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

3 3
1 2
2 1
2 3

Sample Output

1

HINT

100%的数据N<=10000,M<=50000
 
 
tarjan+缩点,最后答案为出度为0的sum,如果有多个出度为0的点,那么答案为0.
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e4+10,maxm=5e4+10;
int n,m;
bool cd[maxn];

int aa,ff;char cc;
int read() {
	aa=0;cc=getchar();ff=1;
	while(cc<'0'||cc>'9') {
		if(cc=='-') ff=-1;
		cc=getchar();
	}
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	return aa*ff;
}

int fir[maxn],nxt[maxm],to[maxm],e=0;
void add(int x,int y) {
	to[++e]=y;nxt[e]=fir[x];fir[x]=e;
}

int zz[maxn],id[maxn],top[maxn],d=0,t=0;
bool vis[maxn],inz[maxn];
int xd[maxn],sum[maxn],tot;
void tj(int pos) {
	id[pos]=top[pos]=++d;
	vis[pos]=inz[pos]=1;
	zz[++t]=pos; int z;
	for(int y=fir[pos];y;y=nxt[y]) {
		z=to[y];
		if(vis[z]) {
			if(inz[z]) top[pos]=min(top[pos],top[z]);
			continue;
		}
		tj(z); top[pos]=min(top[pos],top[z]);
	}
	if(top[pos]==id[pos]) {
		sum[++tot]=0;
		while(t) {
			xd[zz[t]]=tot;
			inz[zz[t]]=0;
			sum[tot]++;
			t--;
			if(zz[t+1]==pos) break;
		}
	}
}

int main() {
	n=read();m=read();
	int x,y,ans=0;
	for(int i=1;i<=m;++i) {
		x=read();y=read();
		add(x,y);
	}
	tj(1);
	for(int i=1;i<=n;++i) for(int y=fir[i];y;y=nxt[y]) {
		if(xd[to[y]]!=xd[i]) cd[xd[i]]=1;
	}
	for(int i=1;i<=tot;++i) if(!cd[i]){
		if(ans) {
			ans=0;
			break;
		}
		ans=sum[i];
	}
	printf("%d",ans);
	return 0;
}

  

posted @ 2017-09-13 17:21  shixinyi  阅读(...)  评论(... 编辑 收藏