/* Author: goats_9 */
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
cin.tie(0)->sync_with_stdio(0);
int n, m;
cin >> n >> m;
vector<vector<int>> g(n), comps, t;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
g[--u].push_back(--v);
g[v].push_back(u);
}
vector<int> s, num(n, -1), low(n, -1), id(n), ap(n);
int timer = 0;
auto dfs = [&] (auto&& self, int u, int p) -> void {
num[u] = low[u] = timer++;
s.push_back(u);
for (int v : g[u]) {
if (v == p) continue;
if (num[v] == -1) {
self(self, v, u);
low[u] = min(low[u], low[v]);
if (num[u] <= low[v]) {
ap[u] = num[u] || num[v] > 1;
comps.push_back({u});
while (comps.back().back() != v) {
comps.back().push_back(s.back());
s.pop_back();
}
}
} else low[u] = min(low[u], num[v]);
}
};
for (int i = 0; i < n; i++) if (num[i] == -1) dfs(dfs, i, -1);
int cnt = 0;
for (int i = 0; i < n; i++) if (ap[i]) id[i] = cnt++, t.push_back({});
for (auto v : comps) {
t.push_back({});
for (int u : v) {
if (ap[u]) {
t[cnt].push_back(id[u]);
t[id[u]].push_back(cnt);
} else {
id[u] = cnt;
}
}
cnt++;
}
vector<int> sz(cnt), dp(cnt, -1), isap(cnt);
for (int u : id) sz[u]++;
for (int i = 0; i < n; i++) if (ap[i]) isap[id[i]] = 1;
ll ans = 0;
auto efs = [&] (auto&& self, int u, int p) -> void {
dp[u] = sz[u];
for (int v : t[u]) {
if (v == p) continue;
self(self, v, u);
ans += 1LL * sz[u] * dp[v] * (dp[v] - 1);
dp[u] += dp[v];
}
ans += 1LL * sz[u] * (n - dp[u]) * (n - dp[u] - 1);
if (isap[u]) {
for (int v : t[u]) {
if (isap[v]) continue;
int z = sz[v] + (int)t[v].size() - 1;
ans -= 1LL * sz[u] * z * (z - 1);
}
}
};
for (int i = 0; i < cnt; i++) if (dp[i] == -1) efs(efs, i, -1);
cout << 1LL * n * (n - 1) * (n - 2) - ans;
return 0;
}