tarjan缩点.
代码较搓OLZ…
AC code:
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <map>
using namespace std;
const int N=10010;
int n,m,cnt,ans;
int dfn[N],low[N],f[N],w[N],ind[N],oud[N],fi[N];
bool ins[N];
stack<int> S;
vector<int> T[N];
vector<int> G[N];
map<int,bool> app[N];
int find(int x){
if(f[x]==x) return x;
f[x]=find(f[x]);
return f[x];
}
void tarjan(int x){
dfn[x]=low[x]=++cnt;
ins[x]=1;
S.push(x);
for(int i=0;i<(int)T[x].size();i++){
int y=T[x][i];
if(!dfn[y]){
tarjan(y);
if(low[y]<low[x]) low[x]=low[y];
}
else if(ins[y]&&dfn[y]<low[x]) low[x]=dfn[y];
}
if(dfn[x]!=low[x]) return ;
while(1){
int t=S.top();
ins[t]=0;
S.pop();
f[t]=x;
if(t==x) return;
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
T[u].push_back(v);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i);
}
for(int i=1;i<=n;i++) fi[i]=i;
for(int i=1;i<=n;i++){
for(int j=0;j<(int)T[i].size();j++){
if(f[i]!=f[T[i][j]]&&(!app[f[i]][f[T[i][j]]])){
oud[f[i]]++;
ind[f[T[i][j]]]++;
app[f[i]][f[T[i][j]]]=1;
G[f[i]].push_back(f[T[i][j]]);
fi[f[i]]=fi[f[T[i][j]]];
}
}
}
for(int i=1;i<=n;i++){
if(f[i]==i) fi[i]=find(fi[i]);
}
int tmp=0;
for(int i=1;i<=n;i++){
if(f[i]==i){
if(tmp&&fi[i]!=tmp){
printf("0\n");
fclose(stdin);
fclose(stdout);
return 0;
}
tmp=fi[i];
}
}
for(int i=1;i<=n;i++) w[f[i]]++;
for(int i=1;i<=n;i++){
if(f[i]==i&&(!oud[i])) ans+=w[i];
}
printf("%d\n",ans);
return 0;
}