//https://blog.csdn.net/anvt77205/article/details/102208781 #include #include #include using namespace std; const int N=5e3+5,NN=N*N; int n,e; int to[NN],ne[NN]; int h[N]; int dfn[N],low[N]; bool b[N]; int s[N];//stack int cnt; int tot,top; int id; int nid[N]; int now; bool no[N]; void add(int u,int v) { to[++cnt]=v; ne[cnt]=h[u]; h[u]=cnt; } void initialise(int n) { cnt=0; tot=0; top=0; id=0; memset(b,0,sizeof(bool)*(n+1)); memset(no,0,sizeof(bool)*(n+1)); memset(h,0,sizeof(int)*(n+1)); memset(dfn,0,sizeof(int)*(n+1));//WA 根据它判断有无经过 } void tarjan(int u) { // printf("%d:",u); int v; dfn[u]=++tot; low[u]=tot; s[++top]=u; b[u]=1; for(int i=h[u]; i; i=ne[i]) { v=to[i]; // printf("%d ",v); if(!dfn[v]) { tarjan(v); low[u]=low[u]0); // printf("\n\n"); } // if(low[u]==dfn[u]) // { // id++; // now=s[top]; // while(dfn[now]!=low[now]) // { // nid[now]=id; // now=s[--top]; // b[now]=0; // } // top--; // b[u]=0; // nid[u]=id; // } } int main() { int u,v; while(~scanf("%d",&n)&&n) { initialise(n); scanf("%d",&e); for(int i=1; i<=e; i++) { scanf("%d%d",&u,&v); add(u,v); } //一开始放在前面,忽略了没有边的情况 for(int i=1; i<=n; i++) { add(0,i); // if(!dfn[i]) // { // tarjan(i); // } } tarjan(0); for(int i=1; i<=n; i++) { for(int j=h[i]; j; j=ne[j]) { v=to[j]; if(nid[v]!=nid[i]) { // printf("no:(%d,%d) ",i,v); no[nid[i]]=1; break; } } } // for(int j=1; j<=n; j++) // { // printf("nid[%d]=%d:%d ",j,nid[j],no[nid[j]]); // } // printf("\n"); for(int j=1; j<=n; j++) { if(!no[nid[j]]) { printf("%d ",j); } } printf("\n"); } return 0; }