#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

#define F first
#define S second
//#define int long long
#define ll long long
//#define int  unsigned long long
#define pb push_back
#define double long double

using namespace std;
using namespace __gnu_pbds;
typedef  tree< int , null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
const int N = 800;
const int K = 60;
const int mod = 998244353;
int g[N][N];
set < int > solve(vector < int > a){
    int n = a.size();
    int v1 = -1;
    int v2 = -1;
  //  for (auto i: a){
  //      cout << i << " ";
  //  }
  //  cout << endl;
    for (int i = 0; i < n; i++){
        int v = a[i];
        if (v1 != -1) break;
        for (int j = i + 1; j < n; j++){
            int u = a[j];
            if (g[v][u] == 0){
                v1 = v;
                v2 = u;
                break;
            }
        }
    }
    set < int > res;
    if (v1 == -1){
        for (int i = 1; i <= n; i++) res.insert(i);
        return res;
    }
    vector < pair < int, int > > b;
    vector < int > used;
    for (int i = 0; i < n; i++){
        if (a[i] == v1){
            b.pb({1, 0});
            used.pb(1);
        }else
        if (a[i] == v2){
            b.pb({0, 1});
            used.pb(1);
        }else{
            int v = a[i];
            b.pb({g[v1][v], g[v2][v]});
            used.pb(0);
        }
    }
  //  cout << "v1 = " << v1 << " v2 = " << v2 << endl;
    int sz1 = 1;
    int sz2 = 1;
    while(1){
        int f = 0;
        for (int i = 0; i < n; i++){
            if (!used[i]){
              //  cout << i << " " << a[i] << " " << b[i].F << " " << b[i].S << " " << sz1 << " " << sz2 << endl;
                if (b[i].F != sz1 && b[i].S != sz2){
                    return res;
                }
                if (b[i].F == sz1 && b[i].S == sz2){
                    continue;
                }
                if (b[i].F == sz1){
                    int v = a[i];
                    sz1++;
                    used[i] = 1;
                    for (int j = 0; j < n; j++){
                        if (!used[j] && g[v][a[j]]){
                            b[j].F++;
                        }
                    }
                }
                if (b[i].S == sz2){
                    int v = a[i];
                    sz2++;
                    used[i] = 1;
                    for (int j = 0; j < n; j++){
                        if (!used[j] && g[v][a[j]]){
                            b[j].S++;
                        }
                    }
                }
                f = 1;
                break;
            }
        }
        if (sz1 + sz2 == n){
            res.insert(sz1);
            res.insert(sz2);
            return res;
        }
        if (f == 0){
            vector < int > nexta;
            for (int i = 0; i < n; i++){
                if (!used[i]) nexta.pb(a[i]);
            }
            set < int > nextres = solve(nexta);
            for (auto j: nextres){
                res.insert(sz1 + j);
                res.insert(sz2 + j);
            }
            return res;
        }
    }
}
main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    //freopen("input.txt", "r", stdin);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++){
        int u, v;
        cin >> u >> v;
        g[u][v] = 1;
        g[v][u] = 1;
    }
    vector < int > v;
    set < int > s;
    for (int i = 1; i <= n; i++) v.pb(i);
    s = solve(v);
    if (s.empty()){
        cout << -1;
        return 0;
    }
    int ans = 1e9;
    for (auto i: s){
        ans = min(ans, i * (i - 1) / 2 + (n - i) * (n - i - 1) / 2);
    }
    cout << ans;
}


Measured memory_bytes: 2560