#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define str string
#define FOR(i,a,b) for(int i = (a) , _b = (b) ; i <= _b ; i++)
#define FOD(i,a,b) for(int i = (a) , _b = (b) ; i < _b ; i++)
#define REP(i,a,b) for(int i = (a) , _b = (b) ; i >= _b ; i--)
#define RED(i,a,b) for(int i = (a) , _b = (b) ; i > _b ; i--)
#define CL(a,x) memset(a,x,sizeof(a))
#define MASK(x) (1LL << (x))
#define fi first
#define se second
#define pii pair<int,int>
#define pb push_back
#define endl '\n'
#define NAME
using namespace std;
const int N = 1e6 + 7 , MOD = 1e9 + 7;
int n, m;
vector<int> a[N];
ll res;
int timeDFS;
ll temp;
int num[N], low[N];
vector<int> bridge_adj[N];
bool check[N];
void DFS(int u, int pre = -1){
num[u] = low[u] = ++timeDFS;
for(int v : a[u]) if(v != pre){
if(!num[v]){
DFS(v, u);
low[u] = min(low[u], low[v]);
if(low[v] > num[u]){
bridge_adj[u].pb(v);
bridge_adj[v].pb(u);
}
}
else low[u] = min(low[u], num[v]);
}
}
void DFS_DAG(int u){
check[u] = true;
temp++;
for(int v : bridge_adj[u])if(!check[v]) DFS_DAG(v);
}
void load(){
FOR(i,1,n) if(!num[i]) DFS(i);
FOR(i,1,n) if(!check[i]){
temp = 0;
DFS_DAG(i);
if (temp >= 3) {
res += ((temp - 1) * (temp - 2)) / 2;
}
}
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin >> n >> m;
FOR(i,1,m){
int u, v;cin >> u >> v;
a[u].pb(v);
a[v].pb(u);
}
load();
cout << res;
return 0;
}
I2luY2x1ZGU8Yml0cy9zdGRjKysuaD4KI2RlZmluZSBsbCBsb25nIGxvbmcKI2RlZmluZSB1bGwgdW5zaWduZWQgbG9uZyBsb25nCiNkZWZpbmUgc3RyIHN0cmluZwojZGVmaW5lIEZPUihpLGEsYikgZm9yKGludCBpID0gKGEpICwgX2IgPSAoYikgOyBpIDw9IF9iIDsgaSsrKQojZGVmaW5lIEZPRChpLGEsYikgZm9yKGludCBpID0gKGEpICwgX2IgPSAoYikgOyBpIDwgX2IgOyBpKyspCiNkZWZpbmUgUkVQKGksYSxiKSBmb3IoaW50IGkgPSAoYSkgLCBfYiA9IChiKSA7IGkgPj0gX2IgOyBpLS0pCiNkZWZpbmUgUkVEKGksYSxiKSBmb3IoaW50IGkgPSAoYSkgLCBfYiA9IChiKSA7IGkgPiBfYiA7IGktLSkKI2RlZmluZSBDTChhLHgpIG1lbXNldChhLHgsc2l6ZW9mKGEpKQojZGVmaW5lIE1BU0soeCkgKDFMTCA8PCAoeCkpCiNkZWZpbmUgZmkgZmlyc3QKI2RlZmluZSBzZSBzZWNvbmQKI2RlZmluZSBwaWkgcGFpcjxpbnQsaW50PgojZGVmaW5lIHBiIHB1c2hfYmFjawojZGVmaW5lIGVuZGwgJ1xuJwojZGVmaW5lIE5BTUUKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKY29uc3QgaW50IE4gPSAxZTYgKyA3ICwgTU9EID0gMWU5ICsgNzsKCmludCBuLCBtOwp2ZWN0b3I8aW50PiBhW05dOwpsbCByZXM7CmludCB0aW1lREZTOwpsbCB0ZW1wOwppbnQgbnVtW05dLCBsb3dbTl07CnZlY3RvcjxpbnQ+IGJyaWRnZV9hZGpbTl07CmJvb2wgY2hlY2tbTl07Cgp2b2lkIERGUyhpbnQgdSwgaW50IHByZSA9IC0xKXsKICAgIG51bVt1XSA9IGxvd1t1XSA9ICsrdGltZURGUzsKICAgIGZvcihpbnQgdiA6IGFbdV0pIGlmKHYgIT0gcHJlKXsKICAgICAgICBpZighbnVtW3ZdKXsKICAgICAgICAgICAgREZTKHYsIHUpOwogICAgICAgICAgICBsb3dbdV0gPSBtaW4obG93W3VdLCBsb3dbdl0pOwogICAgICAgICAgICBpZihsb3dbdl0gPiBudW1bdV0pewogICAgICAgICAgICAgICAgYnJpZGdlX2Fkalt1XS5wYih2KTsKICAgICAgICAgICAgICAgIGJyaWRnZV9hZGpbdl0ucGIodSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZWxzZSBsb3dbdV0gPSBtaW4obG93W3VdLCBudW1bdl0pOwogICAgfQp9Cgp2b2lkIERGU19EQUcoaW50IHUpewogICAgY2hlY2tbdV0gPSB0cnVlOwogICAgdGVtcCsrOwogICAgZm9yKGludCB2IDogYnJpZGdlX2Fkalt1XSlpZighY2hlY2tbdl0pIERGU19EQUcodik7Cn0KCnZvaWQgbG9hZCgpewogICAgRk9SKGksMSxuKSBpZighbnVtW2ldKSBERlMoaSk7CiAgICBGT1IoaSwxLG4pIGlmKCFjaGVja1tpXSl7CiAgICAgICAgdGVtcCA9IDA7CiAgICAgICAgREZTX0RBRyhpKTsKICAgICAgICBpZiAodGVtcCA+PSAzKSB7CiAgICAgICAgICAgIHJlcyArPSAoKHRlbXAgLSAxKSAqICh0ZW1wIC0gMikpIC8gMjsKICAgICAgICB9CiAgICB9Cn0KCmludCBtYWluKCl7CiAgICBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKDApO2Npbi50aWUoMCk7Y291dC50aWUoMCk7CiAgICBjaW4gPj4gbiA+PiBtOwogICAgRk9SKGksMSxtKXsKICAgICAgICBpbnQgdSwgdjtjaW4gPj4gdSA+PiB2OwogICAgICAgIGFbdV0ucGIodik7CiAgICAgICAgYVt2XS5wYih1KTsKICAgIH0KICAgIGxvYWQoKTsKICAgIGNvdXQgPDwgcmVzOwogICAgcmV0dXJuIDA7Cn0K