#include <bits/stdc++.h>   using namespace std;   template <class T>   void debug(T a, T b) {     ;   }   template <class T>   void chmin(T& a, const T& b) {     if (a > b) a = b;   }   template <class T>   void chmax(T& a, const T& b) {     if (a < b) a = b;   }   namespace std {   template <class S, class T>   ostream& operator<<(ostream& out, const pair<S, T>& a) {     out <<  (  << a.first <<  ,  << a.second <<  ) ;     return out;   }   }  // namespace std   long long int readL() {     long long int res;     scanf( %I64d , &res);     return res;   }   void printL(long long int res) { printf( %I64d , res); }   int n, m, n2;   int g[2005][2005];   int order[2005], low[2005], cnt;   stack<int> cur;   int group[2005], gcnt;   int dfs(int v, int p) {     order[v] = cnt++;     low[v] = order[v];     cur.push(v);     for (int i = 0; i < (n); ++i)       if (g[v][i]) {         int to = i;         if (to == p) continue;         if (order[to] != -1) {           low[v] = min(low[v], order[to]);         } else {           low[v] = min(low[v], dfs(to, v));         }       }     if (low[v] < order[v]) return low[v];     while (!cur.empty() && cur.top() != v) {       group[cur.top()] = gcnt;       cur.pop();     }     group[cur.top()] = gcnt;     cur.pop();     ++gcnt;     return low[v];   }   vector<int> g2[2005];   int size[2005];   int subsize[2005];   void prep(int v, int p) {     subsize[v] = size[v];     for (auto to : g2[v]) {       if (to == p) continue;       prep(to, v);       subsize[v] += subsize[to];     }   }   bool tmp[4005];   int dfs2(int v, int p) {     int res = 0;     for (auto to : g2[v]) {       if (to == p) continue;       res += dfs2(to, v);     }     if (p != -1) {       res += size[v] * (subsize[v] - size[v]);     } else {       res += size[v] * (subsize[v] - size[v]);       int sub = subsize[v] - size[v];       memset((tmp), 0, sizeof(tmp));       tmp[0] = true;       for (auto to : g2[v]) {         for (int j = n2; j >= 0; --j)           if (tmp[j]) tmp[j + subsize[to]] = true;       }       int maxi = -1;       for (int i = 0; i < (n2 + 1); ++i)         if (tmp[i]) chmax(maxi, i * (sub - i));       res += maxi;     }     return res;   }   int main() {     cin >> n >> m;     for (int i = 0; i < (m); ++i) {       int a, b;       scanf( %d%d , &a, &b);       --a;       --b;       g[a][b] = g[b][a] = 1;     }     memset(order, -1, sizeof(order));     dfs(0, -1);     n2 = n;     ;     ;     debug(group, group + n);     for (int i = 0; i < (n); ++i) {       size[group[i]]++;       for (int j = 0; j < (n); ++j)         if (g[i][j] && group[i] != group[j] && i > j) {           g2[group[i]].push_back(group[j]);           g2[group[j]].push_back(group[i]);         }     };     ;     n = gcnt;     for (int i = 0; i < (n); ++i) debug((g2[i]).begin(), (g2[i]).end());     int res = 0;     for (int i = 0; i < (n); ++i) {       prep(i, -1);       bool fail = 0;       for (auto to : g2[i])         if (subsize[to] * 2 > n2) {           fail = 1;         }       if (!fail) {         int tmp = dfs2(i, -1);         chmax(res, tmp);       }     }     for (int i = 0; i < (n); ++i) res += size[i] * size[i];     cout << res << endl;     return 0;   }