BZOJ 1051 [HAOI2006]受欢迎的牛

1051: [HAOI2006]受欢迎的牛

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 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

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;}

 

posted @ 2015-08-15 11:50  AI_Believer  阅读(...)  评论(... 编辑 收藏