用状态压缩来表示集合,不妨设 $f(x)$ 表示从 $x$ 出发能够到达的点构成的集合
$$
f(x) = \{x\} \cup \left( \bigcup_{(x, y) \text{存在有向边}} f(y)\right)
$$
const int maxn = 30000 + 10;
int head[maxn], ne[maxn], ver[maxn], deg[maxn], n, m, tot = 0;
vector<int> a;
void add(int x, int y) {
ver[++tot] = y; ne[tot] = head[x]; head[x] = tot;
deg[y]++;
}
void toposort() {
queue<int> q;
for (int i = 1; i <= n; i++) {
if (deg[i] == 0) q.push(i);
}
while (q.size()) {
int x = q.front(); q.pop();
a.push_back(x);
for (int i = head[x]; i; i = ne[i]) {
int y = ver[i];
if (--deg[y] == 0) q.push(y);
}
}
}
bitset<maxn> f[maxn];
void solve() {
for (int j = a.size()-1; j >= 0; j--) {
int x = a[j];
f[x][x] = 1;
for (int i = head[x]; i; i = ne[i]) {
f[x] |= f[ver[i]];
}
}
for (int i = 1; i <= n; i++) printf("%d\n", (int)f[i].count());
}
int main() {
freopen("input.txt", "r", stdin);
cin >> n >> m;
// get edge
memset(head, 0, sizeof head);
for (int i = 0; i < m; i++) {
int x, y;
scanf("%d%d", &x, &y);
add(x, y);
}
toposort();
solve();
}