Description
Input
Output
Sample Input
3 3 1 2 2 1 2 3
Sample Output
1
题解:
考虑以牛为顶点的有向图,对每个需对(A,B)连一条从A到B的边。我们不妨假设两头牛A,B都被其他牛认为是红牛。那么就知道A,B一定同属一个强连通分量,即存在一个包含A,B两个顶点的圈。反之,如果一个牛被其他牛认为是红牛,那么他所属的强连通分量中的牛一定全部是红牛。所以我们只需要找出拓扑序最大的强连通分量的个数就可以了。
AC代码:
1 #include<iostream> 2 #include<cctype> 3 using namespace std; 4 const int MAXN=500000+10; 5 //------------------------- 6 void read(int &x){ 7 x=0;char ch=getchar();int f=1; 8 for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 9 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0'; 10 x*=f; 11 } 12 //------------------------- 13 int n,m,tmp; 14 int topo[MAXN],cmp[MAXN]; 15 bool vis[MAXN]; 16 int first[MAXN],next[MAXN],v[MAXN],e; 17 void AddEdge(int a,int b){ 18 v[++e]=b; 19 next[e]=first[a]; 20 first[a]=e; 21 } 22 23 int rfirst[MAXN],rnext[MAXN],rv[MAXN],re; 24 void rAddEdge(int a,int b){ 25 rv[++re]=b; 26 rnext[re]=rfirst[a]; 27 rfirst[a]=re; 28 } 29 //------------------------- 30 void dfs(int x){ 31 vis[x]=1; 32 for(int i=first[x];i;i=next[i]) 33 if(!vis[v[i]])dfs(v[i]); 34 topo[++tmp]=x; 35 } 36 37 void rdfs(int x,int k){ 38 vis[x]=1; 39 cmp[x]=k; 40 for(int i=rfirst[x];i;i=rnext[i]) 41 if(!vis[rv[i]])rdfs(rv[i],k); 42 } 43 //--------------------------- 44 int k=1; 45 int scc(){ 46 memset(vis,0,sizeof(vis)); 47 memset(topo,0,sizeof(topo)); 48 for(int i=1;i<=n;i++){ 49 if(!vis[i])dfs(i); 50 } 51 memset(vis,0,sizeof(vis)); 52 for(int i=n;i>=1;i--)if(!vis[topo[i]])rdfs(topo[i],k++); 53 return k-1; 54 } 55 //--------------------------- 56 int main(){ 57 read(n);read(m); 58 for(int i=1;i<=m;i++){ 59 int x,y; 60 read(x);read(y); 61 AddEdge(x,y); 62 rAddEdge(y,x); 63 } 64 int nn=scc(); 65 66 int u=0,num=0; 67 for(int i=1;i<=n;i++) 68 if(cmp[i]==nn){u=i;num++;} 69 memset(vis,0,sizeof(vis)); 70 rdfs(u,0); 71 for(int i=1;i<=n;i++) 72 if(!vis[i]){ 73 num=0; 74 break; 75 } 76 printf("%d\n",num); 77 }