std::vector<int> head[MAXN]; int dfn[MAXN], low[MAXN]; bool inStack[MAXN]; int rep[MAXM], ren[MAXM]; // 把输入数据存一下 int sizSC[MAXN], ode[MAXN]; int ftot = 0; int top, Stack[MAXN]; int col, timestamp, SC[MAXN]; // dfn:dfs的时间戳 // low:在点u的子树能到达的节点中dfn的最小值 // SC:点u属于哪一个强连通分量 // inStack:是否在栈中 // sizSC:该强连通分量的大小 // ode:该“点”的出度
voidaddEdge(int x, int y){ head[x].push_back(y); }
voidTarjan(int u){ low[u] = dfn[u] = ++timestamp; Stack[++top] = u; inStack[u] = true; for (int i = 0, siz = (int) head[u].size(); i < siz; ++i) { int v = head[u][i]; if (!dfn[v]) { // 没被访问过 Tarjan(v); low[u] = std::min(low[u], low[v]); } elseif (inStack[v]) low[u] = std::min(low[u], low[v]); } if (dfn[u] == low[u]) { // 意味着u的子树中没有能到达u的祖先的边,也就是找到了一个强连通分量 SC[u] = ++col; inStack[u] = false; ++sizSC[col]; while (Stack[top] != u) { SC[Stack[top]] = col; ++sizSC[col]; inStack[Stack[top--]] = false; } top--; } }
intmain(){ int n, m; scanf("%d %d", &n, &m); for (int i = 1; i <= m; ++i) { int a, b; scanf("%d %d", &a, &b); addEdge(a, b); } for (int i = 1; i <= n; ++i) if (!dfn[i]) Tarjan(i); // 对所有联通块进行tarjan
for (int i = 1; i <= n; ++i) { for (int j = 0, siz = (int) head[i].size(); j < siz; ++j) { int v = head[i][j]; if (SC[i] != SC[v]) ++ode[SC[i]]; } }
int ans = 0; for (int i = 1; i <= col; ++i) if (!ode[i]) { if (ans) { printf("0"); return0; } ans = sizSC[i]; } printf("%d\n", ans); return0; } // tm这题我调了2h