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;
template <class T>
inline void Read(T &x) {
  int f = 1;
  char t = getchar();
  while (t < '0' || t > '9') {
    if (t == '-') f = -1;
    t = getchar();
  }
  x = 0;
  while (t >= '0' && t <= '9') {
    x = x * 10 + t - '0';
    t = getchar();
  }
  x *= f;
}
const int maxn = 2005;
const int maxe = 4000005;
struct graph {
  int fst[maxn], u[maxe], v[maxe], nxt[maxe], e_cn;
  int dfn[maxn], low[maxn], flag[maxn], q[maxn], r, dfn_clock;
  int weight[maxn], belong[maxn], cnt;
  long long G[maxn];
  int Size[maxn];
  bool vis[maxe];
  graph() {
    e_cn = -1, cnt = 0, dfn_clock = 0;
    memset(fst, -1, sizeof(fst));
    memset(vis, 0, sizeof(vis));
    memset(flag, 0, sizeof(flag));
  }
  void addedge(int x, int y) {
    e_cn++;
    u[e_cn] = x, v[e_cn] = y;
    nxt[e_cn] = fst[x], fst[x] = e_cn;
  }
  void tarjan(int cn) {
    dfn[cn] = low[cn] = ++dfn_clock;
    q[++r] = cn, flag[cn] = 2;
    for (register int i = fst[cn]; i != -1; i = nxt[i]) {
      if (!vis[i]) {
        vis[i] = vis[i ^ 1] = true;
        if (!flag[v[i]]) {
          tarjan(v[i]);
          low[cn] = min(low[cn], low[v[i]]);
        } else if (flag[v[i]] == 2) {
          low[cn] = min(low[cn], dfn[v[i]]);
        }
      }
    }
    if (dfn[cn] == low[cn]) {
      int cur;
      cnt++;
      do {
        cur = q[r--];
        belong[cur] = cnt;
        weight[cnt]++;
        flag[cur] = 1;
      } while (cur != cn);
    }
  }
  void restruct(graph &to) {
    to.cnt = cnt;
    for (register int i = 1; i <= cnt; i++) to.weight[i] = weight[i];
    for (register int i = 0; i <= e_cn; i++) {
      int x = u[i], y = v[i];
      if (belong[x] != belong[y]) {
        to.addedge(belong[x], belong[y]);
      }
    }
  }
  long long dfs(int cn, int pr) {
    Size[cn] = weight[cn];
    G[cn] = weight[cn] * weight[cn];
    for (register int i = fst[cn]; i != -1; i = nxt[i]) {
      if (v[i] != pr) {
        dfs(v[i], cn);
        Size[cn] += Size[v[i]];
        G[cn] += G[v[i]];
        G[cn] += weight[cn] * Size[v[i]];
      }
    }
    return G[cn];
  }
  long long calc(int root) {
    static bool f[maxn];
    static vector<int> son;
    son.clear();
    memset(G, 0, sizeof(G));
    memset(Size, 0, sizeof(Size));
    memset(f, 0, sizeof(f));
    long long re = dfs(root, -1), sum = 0, mx = 0;
    f[0] = true;
    for (register int i = fst[root]; i != -1; i = nxt[i])
      son.push_back(Size[v[i]]);
    for (register int i = 0; i < son.size(); i++) {
      int th = son[i];
      sum += th;
      for (register int j = sum; j >= th; j--) f[j] |= f[j - th];
    }
    for (register int i = 0; i <= sum; i++) {
      if (f[i]) mx = max(mx, i * (sum - i));
    }
    return re + mx;
  }
};
int n, m;
graph initgraph, newgraph;
void input() {
  int x, y;
  Read(n);
  Read(m);
  for (register int i = 1; i <= m; i++) {
    Read(x);
    Read(y);
    initgraph.addedge(x, y);
    initgraph.addedge(y, x);
  }
}
void solve() {
  long long ans = 0;
  initgraph.tarjan(1);
  initgraph.restruct(newgraph);
  ans = newgraph.calc(1);
  for (register int i = 1; i <= newgraph.cnt; i++)
    ans = max(ans, newgraph.calc(i));
  cout << ans << endl;
}
int main() {
  input();
  solve();
  return 0;
}
