poj 2553 (强连通缩点出度为0)

  题意 :   一个有向图  , 如果一个点u能够达到点v, v也能到达u, 则u是sink点 ;  找出所有的sink  ,按顺序输入  ;

   注意 如果点u能够到达的所有点中,有一个点不能到达u , u就不算是sink ,必须所有的点都能够达到u  ;

  

   第二组数据  :     1 --> 2   

     1 能到达的点事  1 , 2  

    但2不能到达1  , 所以1不是sink  

   2能够到达的点 是 2 ;

  且2也能够到达2 ; 所有2是sink  ;


    分析  :    求一遍 强连通分量  ,  显然 , 在一个强连通分量的所有点 ,都是sink  ,  并且这个强连通分量是出度为0 的  ;  



#include
#include
#include
#include
#include
#include
#include
#include 
#include
#include
using namespace std ;
const int N=5555 ;
const int M=5000000;
struct node
{
	int u,v,next;
}edge[M];
int head[N],dfn[N],low[N],vist[N],belong[N],out[N],stack[N],ans[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(dfn[u] == low[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",&n))
	{
		   if(n==0) break;
		   scanf("%d",&m) ;
		   top = cnt = sum = dep =0  ;
		   memset(head,-1,sizeof(head));
		   for(int i  = 1  ; i <= m ; i++)
		   {
		   	     scanf("%d%d",&u,&v);
		   	     add(u,v) ;
		   }
		   memset(low,0,sizeof(low));
		   memset(dfn,0,sizeof(dfn)) ;
		   memset(vist,0,sizeof(vist));
		   memset(belong,0,sizeof(belong)) ;
		   memset(out,0,sizeof(out)) ;
		   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  k = 0 ;
		   for(int i = 1 ; i <= n ; i++)
		     {
		     	   if( out[belong[i]]  == 0)
		     	    {
		     	    	  ans[k++]=i ;
		     	    }
		     }     
 
		     printf("%d",ans[0]) ;
		   for(int i = 1 ; i < k ; i++)
		     printf(" %d",ans[i]);     
		       puts("") ;   
	}
	return 0 ;
} 

  

你可能感兴趣的:(强联通图)