http://poj.org/problem?id=2553
#include<iostream> #include<stdio.h> //#include<vector> #include<string.h> #include<stack> using namespace std; //vector <int > g[1002]; struct E{int to;int next;} edge[20000000]; int pre[5002],low[5002],lt_num,c,scc_num[5002],scc,out0[5002],n,adj[5002],num,flag; stack <int >s; void add(int a,int b) { edge[num].to=b; edge[num].next=adj[a]; adj[a]=num++; } void dfs(int u) // 求出每个点的强连通分量标号 { int i,v; pre[u]=low[u]=c++; s.push (u); for(i=adj[u];i!=-1;i=edge[i].next) { v=edge[i].to; if(!pre[v])//!scc_num[v] { dfs(v); if(low[v]<low[u]) low[u]=low[v]; } else if(low[v]<low[u]&&!scc_num[v]) low[u]=low[v]; } if(low[u]==pre[u]) //是该连通分量的 第一个点 { scc++; while(1) { int t=s.top ();s.pop (); scc_num[t]=scc; //scc_num[t]是第scc个强连通分量; if(t==u) break; } } } void solve() { int i,j,v; memset(out0,0,sizeof(out0)); for(i=1;i<=n;i++) for(j=adj[i];j!=-1;j=edge[j].next) { v=edge[j].to; if(scc_num[i]!=scc_num[v]) out0[scc_num[i]]=1; } for(i=1;i<=n;i++) if(!out0[scc_num[i]]) // 缩点后的 出度为0的 点 { flag=1; printf("%d ",i); } } int main() { int i,m,a,b; while(scanf("%d",&n)) { flag=0; if(n==0) break; scanf("%d",&m); memset(adj,-1,sizeof(adj)); while(m--) { scanf("%d%d",&a,&b); add(a,b); } scc=0;c=1;num=0; // 注意c一定不能从0开始 memset(pre,0,sizeof(pre)); memset(scc_num,0,sizeof(scc_num)); for(i=1;i<=n;i++) if(!pre[i]) dfs(i); solve(); printf(" "); if(flag==0) printf(" "); //printf("scc %d ",scc); } return 0; }