Imagine a city with n junctions and m streets. Junctions are numbered from 1 to n.

In order to increase the traffic flow, mayor of the city has decided to make each street one-way. This means in the street between junctions u and v, the traffic moves only from u to v or only from v to u. 

The problem is to direct the traffic flow of streets in a way that maximizes the number of pairs (u, v) where 1 ≤ u, v ≤ n and it is possible to reach junction v from u by passing the streets in their specified direction. Your task is to find out maximal possible number of such pairs.

Input

The first line of input contains integers n and m, (<image>), denoting the number of junctions and streets of the city.

Each of the following m lines contains two integers u and v, (u ≠ v), denoting endpoints of a street in the city.

Between every two junctions there will be at most one street. It is guaranteed that before mayor decision (when all streets were two-way) it was possible to reach each junction from any other junction.

Output

Print the maximal number of pairs (u, v) such that that it is possible to reach junction v from u after directing the streets.

Examples

Input

5 4
1 2
1 3
1 4
1 5


Output

13


Input

4 5
1 2
2 3
3 4
4 1
1 3


Output

16


Input

2 1
1 2


Output

3


Input

6 7
1 2
2 3
1 3
1 4
4 5
5 6
6 4


Output

27

Note

In the first sample, if the mayor makes first and second streets one-way towards the junction 1 and third and fourth streets in opposite direction, there would be 13 pairs of reachable junctions: {(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (2, 1), (3, 1), (1, 4), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5)}
#include <bits/stdc++.h>
using namespace std;
inline int Readint() {
  int ret = 0;
  int f = 1;
  char ch;
  do {
    ch = getchar();
    if (ch == '-') f *= -1;
  } while (ch >= 0 && (ch < '0' || ch > '9'));
  while ('0' <= ch && ch <= '9') {
    ret = ret * 10 + ch - '0';
    ch = getchar();
  }
  return ret * f;
}
void open() {
  freopen("graph.in", "r", stdin);
  freopen("graph.out", "w", stdout);
}
void close() {
  fclose(stdin);
  fclose(stdout);
}
const int MAXM = 1000000 + 10;
const int MAXN = 2050;
int bridge[MAXM] = {0};
int tot;
int to[MAXM];
int nxt[MAXM];
int hd[MAXN];
int belong[MAXN];
int val[MAXN];
int bto[MAXN * 2];
int bnxt[MAXN * 2];
int bhd[MAXN];
int dfn[MAXN];
int low[MAXN];
int df_time;
int dcc_tot;
int fa[MAXN];
int sz[MAXN];
int ans[MAXN];
int dp[MAXN];
int sm[MAXN];
int can[MAXN];
int answer;
int vis[MAXN];
int n, m;
inline void add(const int &x, const int &y) {
  tot++;
  to[tot] = y;
  nxt[tot] = hd[x];
  hd[x] = tot;
}
void init() {
  n = Readint(), m = Readint();
  int u, v;
  tot = -1;
  memset(hd, -1, sizeof(hd));
  for (int i = 1, _END_ = m; i <= _END_; i++) {
    u = Readint(), v = Readint();
    add(u, v);
    add(v, u);
  }
}
void dfs(int p, int fa) {
  dfn[p] = low[p] = ++df_time;
  int cnt = 0;
  for (int i = hd[p]; i != -1; i = nxt[i])
    if ((i ^ 1) != fa) {
      if (!dfn[to[i]]) {
        dfs(to[i], i);
        low[p] = min(low[p], low[to[i]]);
        if (dfn[p] < low[to[i]]) bridge[i ^ 1] = bridge[i] = 1;
      } else
        low[p] = min(low[p], dfn[to[i]]);
    }
}
void tarjan() {
  for (int i = 1, _END_ = n; i <= _END_; i++)
    if (!dfn[i]) dfs(i, -1);
}
void paint(int p) {
  belong[p] = dcc_tot;
  val[dcc_tot]++;
  for (int i = hd[p]; i != -1; i = nxt[i])
    if (!bridge[i]) {
      if (!belong[to[i]]) paint(to[i]);
    }
}
inline void badd(int x, int y) {
  tot++;
  bto[tot] = y;
  bnxt[tot] = bhd[x];
  bhd[x] = tot;
}
int get_fa(int p) {
  if (p == fa[p])
    return fa[p];
  else
    return fa[p] = get_fa(fa[p]);
}
void rebuild() {
  for (int i = 1, _END_ = n; i <= _END_; i++)
    if (!belong[i]) {
      dcc_tot++;
      paint(i);
      answer += val[dcc_tot] * val[dcc_tot];
    }
  tot = 0;
  for (int i = 1, _END_ = dcc_tot; i <= _END_; i++) fa[i] = i, sz[i] = 1;
  int fi, fj;
  for (int p = 1, _END_ = n; p <= _END_; p++)
    for (int i = hd[p]; i != -1; i = nxt[i])
      if (bridge[i]) {
        badd(belong[p], belong[to[i]]);
        fi = get_fa(belong[p]);
        fj = get_fa(belong[to[i]]);
        if (fi != fj) {
          if (sz[fi] < sz[fj]) swap(fi, fj);
          fa[fj] = fi;
          sz[fi] += sz[fj];
        }
      }
}
inline void chkmx(int &a, int b) {
  if (b > a) a = b;
}
void dynamic(int p) {
  vis[p] = 1;
  for (int i = bhd[p]; i; i = bnxt[i])
    if (!vis[bto[i]]) {
      dynamic(bto[i]);
      dp[p] += dp[bto[i]];
      sm[p] += sm[bto[i]];
    }
  dp[p] += val[p] * sm[p];
  sm[p] += val[p];
}
void work() {
  int tmp = 0;
  for (int i = 1, _END_ = dcc_tot; i <= _END_; i++) {
    memset(vis, 0, sizeof(vis));
    memset(dp, 0, sizeof(dp));
    memset(sm, 0, sizeof(sm));
    dynamic(i);
    memset(can, 0, sizeof(can));
    can[0] = 1;
    for (int line = bhd[i]; line; line = bnxt[line])
      for (int val = n, _END_ = sm[bto[line]]; val >= _END_; val--)
        can[val] = max(can[val], can[val - sm[bto[line]]]);
    tmp = 0;
    for (int x = 1, _END_ = n; x <= _END_; x++)
      if (can[x]) {
        if (tmp < x * (n - x - val[i]))
          tmp = x * (n - x - val[i]);
        else
          break;
      }
    chkmx(ans[get_fa(i)], dp[i] + tmp);
  }
  for (int i = 1, _END_ = dcc_tot; i <= _END_; i++)
    if (get_fa(i) == i) answer += ans[i];
  printf("%d\n", answer);
}
int main() {
  int _ = 0;
  init();
  tarjan();
  rebuild();
  work();
  close();
  return 0;
}
