连通分支

#include  < stdio.h >

const   int  LEN  =   10005 ;

int  flag;  // 强连通分支标号

struct HEAD 
// 结点头
{
    
int state; //搜索处在的状态
    int flag; //强连通分支标号
    int count; //结点的出度

    
int next;
    
int last;
}
;
HEAD head1[LEN]; 
// 原图
HEAD head2[LEN];  // 逆图
HEAD head3[LEN];  // 缩点后的图

int  time[LEN];  // 存储结点
int  next_time;

struct 
// 模拟的内存
{
    
int num;
    
int next;
}
node[LEN * 20 ];
int  next_node;

int  hash[LEN];

void  init (  int  n )  // 初始化
{

    
for ( int i=0; i<n; i++ )
    
{
        hash[i] 
= 0;
    }

    flag 
= 0;
    next_node 
= 0;
    next_time 
= 0;
}


void  init_head (  int  n, HEAD  * head )  // 初始化链表
{

    
for ( int i=0; i<n; i++ )
    
{
        head[i].count 
= 0;
        head[i].flag 
= -1;
        head[i].next 
= -1;
        head[i].state 
= 0;
    }

}


void  ins (  int  a,  int  b, HEAD  * head )  // 插入一条边
{

    node[next_node].next 
= -1;
    node[next_node].num 
= b;
    next_node 
++;

    
if ( head[a].next==-1 )
    
{
        head[a].next 
= next_node-1;
    }

    
else
    
{
        node[ head[a].last ].next 
= next_node-1;
    }

    head[a].last 
= next_node-1;
    head[a].count 
++;
}


// 极度简化的堆栈
int  stack[LEN][ 2 ];
int  top;

inline 
void  push(  int  a[] )  // 出堆栈
{

    top 
++;
    stack[top][
0= a[0];
    stack[top][
1= a[1];
}


inline 
int  isempty ()
{

    
return top<0 ? 1:0;
}


void  mark (  int  s, HEAD  * head )  // 对原图进行深搜
{

    
int i;
    
int now[2];
    top 
= -1;

    now[
0= s;
    now[
1= head[s].next;
    push ( now );
    head[ now[
0] ].state = 1;
    
while ( !isempty () )
    
{
        now[
0= stack[top][0];
        now[
1= stack[top][1];
        
for ( i=now[1]; i!=-1; i=node[i].next )
        
{
            
if ( !head[ node[i].num ].state )
            
{
                stack[top][
1= node[i].next;
                now[
0= node[i].num;
                now[
1= head[ node[i].num ].next;
                push ( now );
                head[ now[
0] ].state = 1;
                
break;
            }

        }

        
if ( i==-1 )
        
{
            head[ now[
0] ].state = 2;
            time[ next_time
++ ] = now[0];
            top 
--;
        }

    }

}


void  ser (  int  s, HEAD  * head )
{

    
int i;
    
int now[2];
    top 
= -1;

    now[
0= s;
    now[
1= head[s].next;
    push ( now );
    head[ now[
0] ].state = 1;
    head[ now[
0] ].flag = flag;
    
while ( !isempty () )
    
{
        now[
0= stack[top][0];
        now[
1= stack[top][1];
        
for ( i=now[1]; i!=-1; i=node[i].next )
        
{
            
if ( !head[ node[i].num ].state )
            
{
                stack[top][
1= node[i].next;
                now[
0= node[i].num;
                now[
1= head[ node[i].num ].next;
                push ( now );
                head[ now[
0] ].flag = flag;
                head[ now[
0] ].state = 1;
                
break;
            }

        }

        
if ( i==-1 )
        
{
            head[ now[
0] ].state = 2;
            top 
--;
        }

    }

}


void  work (  int  n, HEAD  * h1, HEAD  * h2, HEAD  * h3 )
{

    
for ( int i=0; i<n; i++ )
    
{
        
if ( !h1[i].state )
        
{
            mark ( i, h1 );
        }

    }

    
for ( int i=next_time-1; i>=0; i-- )
    
{
        
if ( !h2[ time[i] ].state )
        
{
            ser ( time[i], h2 );
            flag 
++;
        }

    }

    
//找极大强连通分支

    init_head ( flag, h3 );
    
for ( int i=0; i<n; i++ )
    
{
        
for ( int j=h2[i].next; j!=-1; j=node[j].next )
        
{
            
if ( h2[i].flag!=h2[ node[j].num ].flag )
            
{
                ins ( h2[ node[j].num ].flag, h2[i].flag, h3 );
            }

        }

    }

    
//缩点

    
for ( int i=0; i<flag; i++ )
    
{
        
if ( !h3[i].count )
        
{
            
for ( int j=0; j<n; j++ )
            
{
                
if ( h2[j].flag==i )
                
{
                    hash[j] 
= 1;
                }

            }

        }

    }

    
for ( int i=0; i<n; i++ )
    
{
        
if ( hash[i] )
        
{
            printf ( 
"%d ", i+1 );
        }

    }

    printf ( 
"\n" );
}


int  main ()
{

    
int n, m;
    
int a, b;
    
while ( scanf ( "%d"&n )!=EOF && n )
    
{
        scanf ( 
"%d"&m );
        init ( n );
        init_head ( n, head1 );
        init_head ( n, head2 );
        
for ( int i=0; i<m; i++ )
        
{
            scanf ( 
"%d%d"&a, &b );
            
if ( a!=b )
            
{
                ins ( a
-1, b-1, head1 );
                ins ( b
-1, a-1, head2 );
            }

        }

        work ( n, head1, head2, head3 );
    }

    
return 0;
}