模板
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 200010, M = 300010;
int n, m, ans[N], head[N][3], nex[N + M * 2], ver[N + M * 2], tot, dfn[N], ord[N], cnt, fth[N], idom[N], semi[N], uni[N], mn[N];
inline void add (int x, int y, int id) {
ver[++ tot] = y;
nex[tot] = head[x][id];
head[x][id] = tot;
}
void tarjan (int x) {
dfn[x] = ++ cnt;
ord[dfn[x]] = x;
for (int i = head[x][0]; i; i = nex[i]) {
int y = ver[i];
if (!dfn[y]) {
fth[y] = x;
tarjan(y);
}
}
}
inline int uni_query (int x) {
if (x == uni[x]) return x;
int tmp = uni_query(uni[x]);
if (dfn[semi[mn[x]]] > dfn[semi[mn[uni[x]]]]) mn[x] = mn[uni[x]];
return uni[x] = tmp;
}
void lengauerTarjan (int s) {
tarjan(s);
for (int i = 1; i <= n; i ++) semi[i] = uni[i] = mn[i] = i;
for (int id = cnt; id >= 2; id --) {
int x = ord[id];
for (int i = head[x][1]; i; i = nex[i]) {
int y = ver[i];
if (!dfn[y]) continue;
uni_query(y);
if (dfn[semi[x]] > dfn[semi[mn[y]]]) semi[x] = semi[mn[y]];
}
uni[x] = fth[x];
add(semi[x], x, 2);
x = fth[x];
for (int i = head[x][2]; i; i = nex[i]) {
int y = ver[i];
uni_query(y);
idom[y] = (x == semi[mn[y]] ? x : mn[y]);
}
head[x][2] = 0;
}
for (int i = 2; i <= cnt; i ++) {
int x = ord[i];
if (idom[x] != semi[x])
idom[x] = idom[idom[x]];
}
}
int main () {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i ++) {
int x, y;
scanf("%d%d", &x, &y);
add(x, y, 0);
add(y, x, 1);
}
lengauerTarjan(1);
for (int i = cnt; i >= 2; i --) {
ans[ord[i]] ++;
ans[idom[ord[i]]] += ans[ord[i]];
}
ans[1] ++;
for (int i = 1; i <= n; i ++) printf("%d ", ans[i]);
return 0;
}