//code by lynmisakura.wish to be accepted!
/****************************/
#include<iostream>
#include<iomanip>
#include<math.h>
#include<vector>
#include<string>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<bitset>
#include <climits>
#include<set>
#include<bitset>
using namespace std;
/***************************/
typedef long long ll;
typedef pair<int,int> pi;
typedef vector<pair<int,int>> vpi;

const long long MOD = 998244353;
const long long mod = 1000000007;
const long long INF = 10000000000000;
 
#define itn int
#define endl "\n"
#define pb push_back
#define mp make_pair
#define ss second
#define ff first
#define mins(x,y) x = min(x,y)
#define maxs(x,y) x = max(x,y)
#define all(x) (x).begin(),(x).end()
#define Rep(n) for(int i = 0;i < n;i++)
#define rep(i,n) for(int i = 0;i < n;i++)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() )
 
ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }
ll qp(ll a, ll b) { ll ans = 1; do { if (b & 1)ans = 1ll * ans*a; a = 1ll * a*a; } while (b >>= 1); return ans; }
ll qp(ll a, ll b, int mo) { ll ans = 1; do { if (b & 1)ans = 1ll * ans*a%mo; a = 1ll * a*a%mo; } while (b >>= 1); return ans; }
 
#define _GLIBCXX_DEBUG
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;
/**************************************************/
#define MAX_N 710
int n,m;
bool G[MAX_N][MAX_N];
vector<int> T[MAX_N];
vector<pair<int,int>> C;
int color[MAX_N];
int blue,red;
bool dp[MAX_N][MAX_N]; //i個目まで見て，j個は実現可能
int sz;
bool check;
/*****************************************************/
//補グラフを作る
void make_graph(){
   for(int i = 0;i < n;i++){
      for(int j = 0;j < n;j++){
         if(!G[i][j]) T[i].pb(j);
      }
   }
}

//補グラフをDFSで連結成分に分解する
//各連結成分が二部グラフになっているかをDFSで判定する（同時に，S,Tへの振り分けを行う）
void dfs(int x,int c){
   if(c == 1) blue++; else if(c == -1) red++;
   color[x] = c;
   for(int i = 0;i < T[x].size();i++){
      int y = T[x][i];
      if(color[y] == c){
         //cout << -1 << endl;
         check = false;
      }
      if(color[y] == 0) dfs(y,c*-1);
   }
}
void do_dfs(){
   for(int i = 0;i < n;i++){
      if(color[i] == 0){
         blue = red = 0;
         dfs(i,1);
         C.pb(mp(blue,red));
      }
   }
   //for(auto i : C) cout << i.ff << " " << i.ss << endl;
}

//完全グラフの辺の数を返す関数
ll ans(int a){
   int b = n - a;
   return a*(a-1)/2 + b*(b-1) / 2;
}
//DPによって頂点の振り分けによって可能なR個（たかだか700まで）を列挙する（ナップザックDP，R個を実現することが可能？）
void do_dp(){
   
   for(int i = 0;i < MAX_N;i++)for(int j = 0;j < MAX_N;j++) dp[i][j] = false;
   
   sz = C.size();
   
   dp[0][C[0].ff] = true;
   dp[0][C[0].ss] = true;
   
   for(int i = 1;i < sz;i++){
      for(int j = 0;j < 701;j++){
         int x = C[i].ff;
         int y = C[i].ss;
         
         if(j - x >= 0 && dp[i-1][j - x])dp[i][j] = true;
         if(j - y >= 0 && dp[i-1][j - y])dp[i][j] = true;
      }
   }
}
//可能なR全てに対して関数の値を全探索して最終的な答えを求める
void result(){
   ll res = INF;
   for(int i = 0;i <= n;i++) if(dp[sz - 1][i]) mins(res,ans(i));
   cout << res << endl;
}
void solve(){
   check = true;
   cin >> n >> m;
   rep(i,n)rep(j,n) if(i != j)G[i][j] = false;else G[i][j] = true;
   rep(i,m){
      int a,b;cin >> a >> b;
      G[--a][--b] = true;
      G[b][a] = true;
   }
   make_graph();
   do_dfs();
   if(!check) goto FIN;
   do_dp();
   result();
   
FIN:;
}
int main(){
   solve();
   if(!check) cout << -1 << endl;
   return 0;
}

Measured memory_bytes: 3584