#include<bits/stdc++.h>
using namespace std;
const int V=3e5+100;
int dfn[V],low[V],parent[V];
bool vis[V];
vector<int> g[V];
int cnt;
int n,m;
int a[V];
void dfs(int u)
{
// 子树数量
int children = 0;
// 默认low[u]等于dfn[u]
dfn[u]=low[u]=++cnt;
vis[u]=true;
// 遍历与u相邻的所有顶点
for(int v:g[u])
{
// 如果这个点没走过
if(!dfn[v])
{
// 递增子树数量
children++;
// 设置v的父亲为u
parent[v]=u;
// 继续DFS
dfs(v);
// DFS完毕,low[v]已求出,如果low[v]<low[u]则更新low[u]
low[u]=min(low[u],low[v]);
// 如果是根节点且有两棵以上的子树则是割点
if(parent[u]==-1&&children>=2) a[u]++;//删去后连通块数量++
//cout << "割点: " << u << endl;
// 如果不是根节点且low[v]>=dfn[u]则是割点
else if(parent[u]!=-1&&low[v]>=dfn[u]) a[u]++;//删去后连通块数量++
//cout << "割点: " << u << endl;
}
// (u, v)为回边,且v不是u的父亲
else if(v!=parent[u])
low[u]=min(low[u],dfn[v]);
}
}
int main(){
memset(parent,-1,sizeof parent);
scanf("%d%d",&n,&m);
int ans=0;
for(int i=0;i<m;i++){
int a,b;scanf("%d%d",&a,&b);
g[a].push_back(b);
g[b].push_back(a);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
++ans;
dfs(i);
}
}
for(int i=1;i<=n;i++){
if(g[i].size()==0) printf("%d",ans-1);
else
printf("%d",ans+a[i]);
i!=n?printf(" "):puts("");
}
return 0;
}