【bzoj1051】 [HAOI2006]受欢迎的牛
题目描述
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶
牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜
欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你
算出有多少头奶牛可以当明星。
输入输出格式
输入格式:
第一行:两个用空格分开的整数:N和M
第二行到第M + 1行:每行两个用空格分开的整数:A和B,表示A喜欢B
输出格式:
第一行:单独一个整数,表示明星奶牛的数量
输入输出样例
输入样例#1:
3 3 1 2 2 1 2 3
输出样例#1:
1
说明
只有 3 号奶牛可以做明星
【数据范围】
10%的数据N<=20, M<=50
30%的数据N<=1000,M<=20000
70%的数据N<=5000,M<=50000
100%的数据N<=10000,M<=50000
题解:
反向建图(好理解),tarjan强连通分量缩点,入度为0的点若只有一个则输出其代表强连通分量的大小,否则无解。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<stack> 6 #define maxn 10005 7 #define maxm 50005 8 using namespace std; 9 int read(){ 10 int x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 struct node{int to,next;}e[maxm]; 16 int n,m,cnt,last[maxn],dfn[maxn],low[maxn],idex=0,Bcnt=0,instack[maxn],v[maxn],belong[maxn],rd[maxn],ans=0,tmp; 17 stack<int> stap; 18 void add(int u,int v){e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;} 19 void tarjan(int s){ 20 int t; 21 dfn[s]=low[s]=++idex; 22 stap.push(s); 23 instack[s]=1; 24 for(int i=last[s];i;i=e[i].next){ 25 t=e[i].to; 26 if(!dfn[t]){ 27 tarjan(t); 28 low[s]=min(low[s],low[t]); 29 } 30 else if(instack[t]) low[s]=min(low[s],low[t]); 31 } 32 if(dfn[s]==low[s]){ 33 Bcnt++; 34 do{ 35 t=stap.top(); 36 stap.pop(); 37 instack[t]=false; 38 belong[t]=Bcnt; 39 v[Bcnt]++; 40 }while(s!=t); 41 } 42 } 43 int main(){ 44 n=read(),m=read(); 45 for(int i=1;i<=m;i++){ 46 int u=read(),v=read(); 47 add(v,u); 48 } 49 for(int i=1;i<=n;i++) 50 if(!dfn[i]) 51 tarjan(i); 52 for(int i=1;i<=n;i++) 53 for(int j=last[i];j;j=e[j].next){ 54 int v=e[j].to; 55 if(belong[i]!=belong[v]) 56 rd[belong[v]]++; 57 } 58 for(int i=1;i<=Bcnt;i++) 59 if(rd[i]==0){ 60 ans++; 61 tmp=i; 62 } 63 if(ans==1) printf("%d",v[tmp]); 64 else printf("0"); 65 return 0; 66 }