BZOJ 1051 [HAOI2006]受欢迎的牛
1051: [HAOI2006]受欢迎的牛
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2909 Solved: 1532
[Submit][Status][Discuss]
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
1 2
2 1
2 3
Sample Output
1
HINT
100%的数据N<=10000,M<=50000
Source
题解:抽象成有向图,缩点后一个点能被所有点访问到的充要条件是出度为一且唯一(呵呵。。。)。。。输出这个大点的数量就行。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar('\n') 9 using namespace std; 10 const int maxn=100000+10,maxm=500000+10; 11 int low[maxn],dfn[maxn],s[maxn],beg[maxn],top,scc,cz,indeg[10001],outdeg[10001];bool ins[maxn]; 12 struct ted{int x,y;ted*nxt;}adj[maxm],*fch[maxn],*ms=adj; 13 void add(int x,int y){*ms=(ted){x,y,fch[x]};fch[x]=ms++;return;} 14 void tarjan(int u){ 15 low[u]=dfn[u]=++cz;ins[u]=true;s[++top]=u; 16 for(ted*e=fch[u];e;e=e->nxt){ 17 int v=e->y;if(!dfn[v])tarjan(v),low[u]=min(low[u],low[v]); 18 else if(ins[v])low[u]=min(low[u],dfn[v]); 19 }if(low[u]==dfn[u]){ 20 scc++;int t=-1;while(t!=u)beg[t=s[top--]]=scc,ins[t]=false; 21 }return; 22 } 23 inline int read(){ 24 int x=0,sig=1;char ch=getchar(); 25 while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();} 26 while(isdigit(ch))x=10*x+ch-'0',ch=getchar(); 27 return x*=sig; 28 } 29 inline void write(int x){ 30 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 31 int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; 32 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 33 } 34 void count_edge(){ 35 for(ted*e=adj;e!=ms;e++){ 36 int x=e->x,v=e->y; 37 if(beg[x]!=beg[v])outdeg[beg[x]]++,indeg[beg[v]]++; 38 }return; 39 } 40 int n,m; 41 void init(){ 42 n=read();m=read();int x,y; 43 for(int i=1;i<=m;i++)x=read(),y=read(),add(x,y); 44 for(int i=1;i<=n;i++)if(dfn[i]==0)tarjan(i); 45 count_edge(); 46 int s=0,st; 47 for(int i=1;i<=scc;i++)if(!outdeg[i])s++,st=i; 48 if(s==0||s>=2)puts("0"); 49 else{ 50 int sum=0; 51 for(int i=1;i<=n;i++)if(beg[i]==st)sum++; 52 write(sum); 53 } 54 return; 55 } 56 void work(){ 57 return; 58 } 59 void print(){ 60 return; 61 } 62 int main(){init();work();print();return 0;}