http://poj.org/problem?id=1236
#include<iostream> #include<stdio.h> #include<vector> #include<string.h> #include<stack> using namespace std; vector <int > g[1002]; int pre[1002],low[1002],lt_num,c,scc_num[1002],scc,in0[1002],out0[1002],n,a,b; stack <int >s; void dfs(int u) { int i,v; pre[u]=low[u]=c++; s.push (u); for(i=0;i<g[u].size ();i++) { v=g[u][i]; 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; } } } int solve() { if(scc==1) return 0; int i,j,v; a=0,b=0; for(i=0;i<=scc;i++) in0[i]=out0[i]=0; for(i=1;i<=n;i++) for(j=0;j<g[i].size ();j++) { v=g[i][j]; if(scc_num[i]!=scc_num[v]) out0[scc_num[i]]++,in0[scc_num[v]]++; } for(i=1;i<=scc;i++) { if(!in0[i]) a++; if(!out0[i]) b++; } return a>b?a:b; } int main() { int i,q; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++) g[i].clear (); for(i=1;i<=n;i++) { while(scanf("%d",&q)) { if(q==0) break; g[i].push_back (q); } } c=1; scc=0;lt_num=0; memset(pre,0,sizeof(pre)); memset(scc_num,0,sizeof(scc_num)); for(i=1;i<=n;i++) if(!pre[i]) { lt_num++; dfs(i); } if(scc==1)
{ printf("1 0 "); continue; } int as=solve(); printf("%d ",a); printf("%d ",as); while(!s.empty ()) s.pop (); } return 0; }