/* 题意: 给一个有向图,问有多少个点,是其他点都可以到达的 其他点都可以到达该点,那么将图转置,就变为该点可以到达其他所有的点 要找这样的点方法有很多,仿照Floyd的DP方法就是最容易写,但是点太多达到10000,会超时 这里用SCC来做 将转置后的图进行缩点,得到一个DAG,这个DAG每个大点内的小点(即原来的点)都是相互可达,关键是看这些大点能不能 去到其他大点,如果一个大点能去到其他所有的大点,那么里面的小点也可以 所以就是要找,有多少个大点,可以去到所有其他的大点,可知这样的大点,最多1个!!,而且是入度为0的点 (这个不难理解,可以思考一下) 找到了这个大点,那么里面包含的小点就都是可以的,所以扫描所有的小点,看是不是属于这个大点的,就可以计数了 */ #include <cstdio> #include <cstring> #define N 10010 #define M 50010 #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) int n,tot; int dcnt,bcnt,top; int stack[N]; bool ins[N]; int dfn[N],low[N],belong[N]; int inde[N],outde[N]; int head[N]; struct edge { int u,v,next; }e[M]; void add(int u ,int v , int k) { e[k].u = u; e[k].v = v; e[k].next = head[u]; head[u] = k; } void tarjan(int u) { stack[++top] = u; ins[u] = true; dfn[u] = low[u] = ++dcnt; for(int k=head[u]; k!=-1; k=e[k].next) { int v = e[k].v; if(!dfn[v]) { tarjan(v); low[u] = min(low[u] , low[v]); } else if(ins[v]) low[u] = min(low[u] , dfn[v]); } if(dfn[u] == low[u]) { ++bcnt; while(1) { int x = stack[top--]; ins[x] = false; belong[x] = bcnt; if(x == u) break; } } } int main() { scanf("%d%d",&n,&tot); memset(head,-1,sizeof(head)); for(int i=0; i<tot; i++) { int u,v; scanf("%d%d",&u,&v); add(v,u,i); } memset(dfn,0,sizeof(dfn)); memset(ins,false,sizeof(ins)); dcnt = bcnt = top = 0; for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i); memset(inde,0,sizeof(inde)); memset(outde,0,sizeof(outde)); for(int i = 0; i<tot; i++) { int u = belong[e[i].u]; int v = belong[e[i].v]; if(u != v) { ++outde[u]; ++inde[v]; } } int c = 0 , x = 1; for(int i=1; i<=bcnt; i++) if(!inde[i]) { c++; x = i; } if(c != 1) printf("0\n"); //大点只可以有1个 else { int c = 0; for(int i=1; i<=n; i++) if(belong[i] == x) c++; printf("%d\n",c); } return 0; }