#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const int N = 110,M = 110;
struct edge{
int to,nxt;
}e[M]; //边的集合
int vis[N]; //标记是否在栈中
int stk[N]; //维护栈
int belong[N]; //各顶点属于哪个强连通分量
int dfn[N]; //时间戳
int low[N]; //u或u的子树能够追溯到的最早的栈中节点的序号(时间戳)
int cnt; //序号(dfn)
int top; //栈顶
int tcnt; //强连通分量计数器
int n,m,head[N],tot;
inline int read(){
int f=0,x=0;
char ch=getchar();
while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
inline void add(int u,int v){
e[++tot].to=v;
e[tot].nxt=head[u];
head[u]=tot;
}
inline void tarjan(int u){
dfn[u]=low[u]=++cnt;
vis[u]=true;
stk[++top]=u;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
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]){
tcnt++;
int v;
do{
v=stk[top--];
vis[v]=false;
belong[v]=tcnt;
}while(u!=v);
}
}
inline void solve(){
for(int i=1;i<=n;++i)
if(!dfn[i])
tarjan(i);
}
signed main(){
n=read();m=read();
for(int i=1;i<=m;++i){
int u=read(),v=read();
add(u,v);
}
solve();
for(int i=1;i<=n;++i)
printf("%d ",belong[i]);
return 0;
}
/*
6 8
1 2
1 3
2 4
3 4
3 5
4 1
4 6
5 6
ans:3 3 3 3 2 1
*/