#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
struct node{
int next,to;
}edge[maxn*10];
ll head[maxn],low[maxn],dfn[maxn];
ll ans[maxn],size[maxn];//ans为答案,size[i]存储以i为根子树的大小
int n,m,cnt,tot;
void add(int u,int v)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void tarjan(int u)
{
low[u]=dfn[u]=++tot;
ll z=0;//记录已求出割点后集合的大小,相当于上面列子左边的集合
size[u]=1;//初始
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(!dfn[v])
{
tarjan(v);
size[u]+=size[v];//没遍历过当然要加上子树的大小,来求出以u为根子树的大小
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])//v为割点
{
ans[u]+=(ll)z*size[v];//模拟上面例子乘的过程
z+=size[v];//记得集合变大
}
}
else
low[u]=min(low[u],dfn[v]);
}
ans[u]+=(ll)z*(n-1-z);//不要忘了,这是最后一步(不只要具体用处,个人理解是算不是割点时的答案)
}
int main()
{
cnt=tot=0;
memset(head,-1,sizeof(head));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(ans,0,sizeof(ans));
memset(size,0,sizeof(size));
int x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
tarjan(1);
for(int i=1;i<=n;i++)
printf("%lld\n",(ans[i]+n-1)<<1);
return 0;
}