传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1051
一开始想网络流去了(跪。。。
后来发现肥肠简单,只用强连通缩点之后看一下出度为0的分量个数,如果只有一个那就合法,这个强连通分量里面的所有点都可以被其他点到达,所以输出这个分量里面的点数,否则(出度为0的连通分量大于1)就输出0
code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10010;
const int maxm=50010;
struct node
{
int x,y,next;
}a[maxm*4],b[maxm*4];
int len,last[maxn];
int elen,elast[maxn];
int st,ed;
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
}/*
void eins(int x,int y)
{
elen++;
b[elen].x=x;b[elen].y=y;
b[elen].next=elast[x]; elast[x]=elen;
}*/
int low[maxn],dfn[maxn],id;
int sta[maxn],top; bool insta[maxn];
int bl[maxn],scc;
int list[maxm*4],head,tail;
int sum[maxn];
void dfs(int x)
{
dfn[x]=low[x]=++id;
sta[++top]=x; insta[x]=true;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(dfn[y]==-1)
{
dfs(y);
low[x]=min(low[x],low[y]);
}
else if(insta[y]) low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x])
{
scc++; int i;
do{
i=sta[top--];
bl[i]=scc;
insta[i]=false;
sum[scc]++;
}while(i!=x);
}
}
int chu[maxn];
void rebuild()
{
for(int i=1;i<=len;i++)
{
if(bl[a[i].x]!=bl[a[i].y])
{
//eins(bl[a[i].x],bl[a[i].y]);
chu[bl[a[i].x]]++;
}
}
}
int main()
{
int n,m;scanf("%d%d",&n,&m);
memset(last,0,sizeof(last)); len=0;
for(int i=1;i<=m;i++)
{
int x,y;scanf("%d%d",&x,&y);
ins(x,y);
}
memset(dfn,-1,sizeof(dfn));
id=top=scc=0;
for(int i=1;i<=n;i++)
if(dfn[i]==-1)
dfs(i);
//memset(elast,0,sizeof(elast)); elen=0;
rebuild();
int cnt=0,tmp=0;
for(int i=1;i<=scc;i++)
{
if(chu[i]==0)
{
cnt++; if(cnt>1){printf("0\n"); return 0;}
tmp=sum[i];
}
}
printf("%d\n",tmp);
return 0;
}