//Tarjan算法(将强连通分量缩度再进行处理) //POJ 2186 #include<iostream> #include<cstdio> #include<stack> #include<vector> #include<cstring> #include<algorithm> using namespace std; const int maxn = 1e4 + 15; vector<int> Grape[maxn]; int cnt;//缩度的节点个数 int arr[maxn];//缩点的标号 bool vis[maxn]; int dfn[maxn],low[maxn],total;//total用来标序号 int du[maxn]; stack<int> s; void tarjan(int u) { dfn[u] = low[u] = ++total; s.push(u); vis[u] = true;//入栈 for(int i=0;i!=Grape[u].size();++i) { int v = Grape[u][i]; if(!dfn[v]) { tarjan(v); low[u] = min(low[u],low[v]); }else if(vis[v])//如果在栈中存在 { low[u] = min(low[u],dfn[v]); } } if(dfn[u]==low[u])//如果节点为强连通图的根 { int v = 0; ++cnt; do{ v = s.top(); s.pop(); vis[v] = false; arr[v] = cnt; }while(u!=v); } } int main() { int n,m; while(cin>>n>>m)//n个节点,m条边 { for(int i=1;i<=n;++i) Grape[i].clear(); int u,v; for(int i=1;i<=m;++i) { cin>>u>>v; Grape[u].push_back(v); } //Tarjan算法缩度 cnt = 0,total = 0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(du,0,sizeof(du));//Judge node不为 0 的出度个数 memset(arr,0,sizeof(arr)); for(int u=1;u<=n;++u) { if(!dfn[u]) { tarjan(u); } } for(int u=1;u<=n;++u) { for(int i=0;i!=Grape[u].size();++i) { int v = Grape[u][i]; if(arr[u]!=arr[v]) ++du[arr[u]];//u 节点所在的环 } } int num = 0,pos = 0; for(int v=1;v<=cnt;++v) { if(du[v]==0) { ++num; pos = v; } } if(num!=1) cout<<0<<endl; else{ int ans = 0; for(int i=1;i<=n;++i) if(arr[i]==pos) ++ans; cout<<ans<<endl; } } }