#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<vector>
#include<algorithm>
#define int __int128
#define maxn 501000
#define maxm 2000010
using namespace std;
namespace lin
{
int read()
{
int now=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-') f=-f;
c=getchar();
}
while(c>='0'&&c<='9')
{
now=(now<<1)+(now<<3)+(c^48);
c=getchar();
}
return now*f;
}
struct linlin
{
int nxt,to;
}jia[maxm*4];
int head[maxn],cnt;
void add(int from,int to)
{
jia[cnt].nxt=head[from];
jia[cnt].to=to;
head[from]=cnt++;
return;
}
vector<int>too[maxm*3];
void addd(int from,int to)
{
too[from].push_back(to);
return;
}
int dep[maxn],low[maxn],stack[maxn*5],top,cnts,vis[maxn],tot;
int ans=0,sum=0,w[maxn*3],n;
void tarjan(int rt,int from)
{
sum++;
dep[rt]=low[rt]=++cnts;
stack[++top]=rt;
w[rt]=-1;
for(int i=head[rt];~i;i=jia[i].nxt)
{
int to=jia[i].to;
if((i^1)==from) continue;
if(!dep[to])
{
int lst=top;
tarjan(to,i);
low[rt]=min(low[rt],low[to]);
if(low[to]>=dep[rt])
{
top--;
tot++;
int wjll=0;
addd(n+tot,rt);
addd(rt,tot+n);
wjll++;
if(top==lst)
{
top++;
}
while(top>lst)
{
addd(n+tot,stack[top]);
addd(stack[top],n+tot);
wjll++;
if(stack[top]==rt)
vis[stack[top]]=0;
else
vis[stack[top]]=1;
top--;
}
w[n+tot]=wjll;
}
}
else
{
if(!vis[to])
stack[++top]=rt;
low[rt]=min(low[rt],dep[to]);
}
}
return;
}
int siz[maxn];
void dfs(int rt,int fa)
{
siz[rt]=(rt<=n);
int sizz=too[rt].size();
for(int i=0;i<sizz;i++)
{
int to=too[rt][i];
if(to==fa) continue;
dfs(to,rt);
ans+=2ll*siz[to]*siz[rt]*w[rt];
siz[rt]+=siz[to];
}
ans+=2ll*(sum-siz[rt])*siz[rt]*w[rt];
return;
}
int love(int wjl)
{
n=read();
int m=read();
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
{
if(!dep[i])
{
sum=0;
top=0;
tarjan(i,-1);
dfs(i,0);
}
}
printf("%lld",(long long)ans);
return wjl;
}
}
signed main()
{
return lin::love(0);
}