void main(){
  import std.stdio, std.string, std.conv, std.algorithm;
  import std.exception, std.typecons;

  int n, m; rd(n, m);
  auto edges=new Tuple!(int, int)[](m);
  auto g=new int[][](n, 0);
  foreach(i; 0..m){
    int a, b; rd(a, b);
    a--; b--;
    g[a]~=b; g[b]~=a;
    edges[i]=tuple(a, b);
  }

  auto vis=new bool[](n);
  long dfs(int i){
    vis[i]=true;
    long ret=1;
    foreach(j; g[i]){
      if(vis[j]==false) ret+=dfs(j);
    }
    return ret;
  }

  long[] sz;
  foreach(i; 0..n){
    if(vis[i]==false) sz~=dfs(i);
  }
  enforce(sz.length>=2);
  
  long cul(int v){
    long num=sz[v];
    foreach(i; 2..(sz.length)) num+=sz[i];
    auto ret=num*(num-1)/2;
    auto u=v^1;
    ret+=sz[u]*(sz[u]-1)/2;
    ret-=m;
    return ret;
  }

  writeln(max(cul(0), cul(1)));
}

void rd(T...)(ref T x){
  import std.stdio, std.string, std.conv;
  auto l=readln.split;
  assert(l.length==x.length);
  foreach(i, ref e; x){
    e=l[i].to!(typeof(e));
  }
}
void wr(T...)(T x){
  import std.stdio;
  foreach(e; x) write(e, " ");
  writeln();
}