#include <bits/stdc++.h>

using namespace std;

using LL = long long;           using PII = pair<int, int>;
using ll = long long;           using DBL = double;
using VI = vector<int>;         using VD = vector<DBL>;
using VVI = vector<VI>;         using VVD = vector<VD>;
#define FOR(i,a,b) for(int i = a; i < b; i++)
#define REP(i,n) FOR(i,0,n)
#define SZ(a) ((int)((a).size()))
#define ALL(x) (x).begin(), (x).end()
#define SET(a,v) memset((a), (v), sizeof(a))
#define EB emplace_back #define PB push_back
#define MP make_pair  #define ST first  #define ND second

// #define trace(...) {__f(#__VA_ARGS__, __VA_ARGS__);}
// template<typename Arg> void __f(const char* name, Arg&& arg) {
//   cerr << name << " = " << arg << std::endl;
// } template <typename Arg1, typename... Args>
// void __f(const char* names, Arg1&& arg1, Args&&... args) {
//   const char* comma = strchr(names + 1, ',');
//   cerr.write(names, comma - names) << " = " << arg1<<" | ";__f(comma+1, args...); }
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds; // OST: find_by_order, order_of_key
// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// #pragma GCC optimize("Ofast")
// optimize("unroll-loops")
// target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
// /*** RNGS ***/
// SEED=chrono::steady_clock::now().time_since_epoch().count();
// // or high_resolution_clock
// mt19937 rng(SEED); /*or*/ random_device rd; mt19937 rng(rd());
// uniform_int_distribution<> dis(MIN, MAX);// usage: dis(rng)
// struct chash {int operator()(int x) const {return x^SEED;}};
// gp_hash_table<int,int,chash>m;//use cc if very less updates
// /*** FAST IO ***/
// inline int scan(){ bool y=0; int x=0; char c=getchar_unlocked();
// while(c<'0'||c>'9'){ if(c=='-')y=1; c=getchar_unlocked();} 
// while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar_unlocked();}
// return y?-x:x; }

int vis[710], col[710], dp[710][710];
vector<int> g[710];
vector<vector<int>> component;

void dfs(int u, int c) {
	vis[u] = 1;
	col[u] = c;
	++component.back()[c];
	for(auto&v: g[u]) {
		if(vis[v]) {
			if(col[v] == c) {
				cout << "-1\n";
				exit(0);
			}
		}
		else {
			dfs(v, 1-c);
		}
	}
}

set<PII> s;

int calc(int pos, int K) {
	int &y = dp[pos][K];
	if(y!=-1) return y;
	if(SZ(component) == pos) {
		return y = (K == 0);
	}
	y = 0;
	if(component[pos][0] <= K) y|= calc(pos+1, K-component[pos][0]);
	if(component[pos][1] <= K) y|= calc(pos+1, K-component[pos][1]);
	return y;
}

int C2(int n) {
	return (n*(n-1))/2;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	SET(dp, -1);
	int n, m;
	cin >> n >> m;
	while(m--) {
		int a, b;
		cin >> a >> b;
		s.insert({a, b});
		s.insert({b, a});
	}
	for(int i=1; i<=n; ++i) {
		for(int j=i+1; j<=n; ++j) {
			if(s.count({i, j}) == 0) {
				g[i].push_back(j);
				g[j].push_back(i);
			}
		}
	}
	for(int i=1; i<=n; ++i) {
		if(!vis[i]) {
			component.push_back({0, 0});
			dfs(i, 0);
		}
	}
	int ans = INT_MAX;
	for(int i=0; i<=n; ++i) {
		if(calc(0, i)) {
			ans = min(ans, C2(i) + C2(n-i));
		}
	}
	cout << ans << endl;
	return 0;
}

Measured memory_bytes: 25216