poj 2186 (强连通缩点传递关系)

题意:有N头牛 每一头牛都梦想着成为popular cow,(但这是不可能滴) 有m组仰慕的关系,仰慕有传递性比如说A觉得B

是popular and B thinks C is popular, then A thinks C is popalur also;

现在问有多少头牛是会被其他牛都仰慕。

思路:求强连通分量,缩成点 点内的头当然是相互仰慕的咯!! 然后求新的图 的出度 出度也0的点就会被所有牛仰慕算出出度为0的强连通分量里点的个数就OK了,注意 可能有多个出度为0的点,这时输出0 ;


#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<queue>
#include <iomanip>
#include<iostream>
#include<algorithm>
using namespace std ;
const  int N= 11111 ;
const  int M= 55555 ;
 struct node
 {
 	int u ,v,next;
 }edge[M] ;
 int head[N],low[N],dfn[N],vist[N],stack[N],belong[N],out[N] ;
 int top ,sum,cnt,dep ;
 
 void add(int u ,int v)
 {
 	  edge[top].u=u;
 	  edge[top].v=v;
 	  edge[top].next=head[u];
 	  head[u]=top++;
 }
 
 void tarjan(int u )
 {
     low[u]=dfn[u]=++dep;
     stack[cnt++]=u;
     vist[u]=1;
     for(int i = head[u] ; i!=-1 ; i=edge[i].next)
     {
     	      int  v= edge[i].v ;
			   if(!dfn[v])
			   {
			   	      tarjan(v) ;
			   	      low[u] = min(  low[u] , low[v] ) ; 
			   }else if(vist[v])
			     low[u] = min(  low[u] , dfn[v] ); 
     }
 	if(low[u] == dfn[u])
 	{
 		  int x;
 		  sum++ ;
 		  do
 		  {
 		  	    x=stack[--cnt] ;
				 vist[x] = 0 ;
				belong[x]=sum;    
 		  }while(x!=u) ;
 	}
 }
 
 
 int main()
 {
 	int n,m,u,v ;
 	while(~scanf("%d%d",&n,&m))
 	{
 		   top  = sum = dep = cnt = 0;
 		   memset(head,-1,sizeof(head));
 		   memset(out,0,sizeof(out));
 		   memset(belong,0,sizeof(belong));
 		   memset(low,0,sizeof(low)) ;
 		   memset(dfn,0,sizeof(dfn)) ;
 		   memset(vist,0,sizeof(vist)) ;
 		   for(int i = 1 ; i <= m ; i++)
 		   {
 		   	  scanf("%d%d",&u,&v) ;
 		   	  add(u,v);
 		   }
 		   for(int i = 1 ; i <= n ; i++)
 		       if(!dfn[i])
 		          tarjan(i) ;
 		//  printf("%d*  ",sum);
		   for(int i = 1 ; i <= n ; i++)
		     for(int j = head[i] ; j!=-1; j=edge[j].next)
			 {
			 	       int  v = edge[j].v ;
			 	       if(belong[i] != belong[v])
			 	       {
			 	       	    out[belong[i]]++;
			 	       }
			 } 	 
		 int flag = 0 , k ;
		 for(int i = 1 ; i <= sum ; i++)
		      if(out[i] == 0  )
			  {
			  	   k=i ;
			  	   flag++;
				   if(flag > 1)
				     break ;	   
			  }
			   
 		   if( flag > 1 )
 		   {
 		   	    printf("0\n");
 		   }
 		   else 
 		   {
 		   	      int ans = 0 ;
 		   	      for(int i = 1 ; i <= n ; i++)
 		   	         if(belong[i] == k)
 		   	              ans++;
 		   	       printf("%d\n",ans);       
 		   }
 	}
 	return 0;
 }


你可能感兴趣的:(poj 2186 (强连通缩点传递关系))