题目链接:http://poj.org/problem?id=3180
题意:有N头奶牛,和M个绳索。每个绳索从一头奶牛处发出,射向另一头奶牛。现在奶牛们想要跳舞,如果沿着射向它的绳索往回找,找到另一头牛,并如此找下去,最后能找到自己发出的绳索,那么这头奶牛就跳舞成功了,并且在寻找过程中,串起来的这些奶牛属于同一个集合。问最后这M个绳索连出了几个集合?
就是求元素大于1的强连通分量数,用tarjan模板即可。
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<stack>
#define N 11000
using namespace std;
vector<int> r[N];
stack<int>s;
int scnt,n,m,cnt,ans,v[N],dfn[N],low[N],belong[N];
void init()
{
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(v,0,sizeof(v));
memset(belong,0,sizeof(belong));
for(int i=0;i<=n;i++) r[i].clear();
scnt=cnt=ans=0;
}
void tarjan(int u)
{
int t;
dfn[u]=low[u]=cnt++;
s.push(u);
v[u]=1;
for(int i=0;i<r[u].size();i++)
{
int c=r[u][i];
if(!dfn[c])
{
tarjan(c);
low[u]=min(low[u],low[c]);
}
else if(v[c])
low[u]=min(low[u],dfn[c]);
}
if(dfn[u]==low[u])
{
scnt++;
int num=0;
do
{
t=s.top();
s.pop();
v[t]=0;
belong[t]=scnt;
num++;
}while(t!=u);
if(num>1) ans++;
}
}
void solve()
{
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
r[u].push_back(v);
}
solve();
cout<<ans<<endl;
}
}