连通分支
#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;
}
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;
}