문제 해결
\ (Tarjan \) 각 지점의 포인트 삭감 통계 후.
점 (A)에 복수 존재하는 경우 (0 \)를 \ , 직접 출사 \ (0 \) 또는 출력의 정도 \ (0 \)는 강하게 연결된 구성 요소의 포인트 수이다.
코드
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#define gI gi
#define itn int
#define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
inline int gi()
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
int n, m, tot, head[100003], nxt[100003], ver[100003], vis[100003];
int x, y, dfn[100003], low[100003], sta[100003], sy[100003], ys[100003];
int num, cnt, sum, ans, kok;
int cd[100003];
inline void add(int u, int v)
{
ver[++tot] = v, nxt[tot] = head[u], head[u] = tot;
}
void Tarjan(int u)//Tarjan缩点
{
dfn[u] = low[u] = ++num; sta[++cnt] = u; vis[u] = 1;
for (int i = head[u]; i; i = nxt[i])
{
int v = ver[i];
if (!dfn[v])
{
Tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (vis[v]) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u])
{
int y;
++kok;
do
{
y = sta[cnt--];
vis[y] = 0;
sy[y] = kok;
++ys[kok];//统计强连通分量里点的个数
} while (y != u);
}
}
int main()
{
//File("P2341");
n = gi(), m = gi();
for (int i = 1; i <= m; i+=1)
{
int u = gi(), v = gi();
add(u, v);
}
for (int i = 1; i <= n; i+=1) if (!dfn[i]) Tarjan(i);
for (int i = 1; i <= n; i+=1)
{
for (int j = head[i]; j; j = nxt[j])
{
int u = ver[j];
if (sy[i] != sy[u])
{
++cd[sy[i]];//统计出度
}
}
}
int fl = 0;
for (int i = 1; i <= kok; i+=1)
{
if (!cd[i])//出度为0
{
if (fl) {puts("0"); return 0;}//有多个出度为0的点,直接输出0
fl = i;//记录答案所在的强连通分量的编号
}
}
printf("%d\n", ys[fl]);//输出答案
return 0;
}