tarjan判断强连通分量 缩点
强连通分量请膜拜大神
http://blog.csdn.net/xinghongduo/article/details/6195337
http://blog.csdn.net/xinghongduo/article/details/6196292
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<vector>
#define cl(x) memset(x,0,sizeof(x))
#define N 10010
using namespace std;
struct Stack
{
int stack[N],top_;
Stack(){top_=0;}
void clear(){top_=0;}
inline void push(int x){stack[++top_]=x;}
inline void pop(){--top_;}
inline int top(){return stack[top_];}
}stack;
vector<int> G[N];
int n,m,dfn[N],low[N],cnt=0,time=0,in[N],out[N],pos=0,ans=0,f[N],C=0,map[N];
bool vis[N],is_point[N],flag=1;
void get_smaller()
{
C++;
int v=stack.top();
while(dfn[v]!=low[v])
{
map[v]=C;
stack.pop();
v=stack.top();
}
map[v]=C;
stack.pop();
}
void tarjan(int v)
{
dfn[v]=low[v]=++time;
vis[v]=1;
stack.push(v);
for(int i=0;i<G[v].size();i++)
if(!dfn[G[v][i]])
{
tarjan(G[v][i]);
low[v]=min(low[v],low[G[v][i]]);
}else
if(vis[G[v][i]])
low[v]=min(low[v],dfn[G[v][i]]);
if(dfn[v]==low[v])get_smaller();
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
}
cl(dfn);cl(low);cl(vis);
for(int i=1;i<=n;i++)f[i]=i;
memset(is_point,1,sizeof(is_point));
for(int i=1;i<=n;i++)
if(!vis[i])tarjan(i);
for(int i=1;i<=n;i++)
{
if(out[map[i]])continue;
for(int j=0;j<G[i].size();j++)
{
if(map[i]!=map[G[i][j]]){out[map[i]]=1;break;}
}
}
for(int i=1;i<=C;i++)
{
if(out[i])cnt++;
else pos=i;
}
if(cnt!=C-1){puts("0");return 0;}
else{
for(int i=1;i<=n;i++)if(map[i]==pos)ans++;
}
printf("%d\n",ans);
return 0;
}