对于完全子图,考虑补图性质,即图内任意两个均无边。
若原图可分为两个完全子图,那么补图内子图无边,两子图间可有边,这不正是二分图吗?
染色判断奇环无解,求出每连通块答案,可行性 DP
计算答案即可。
时间复杂度 O ( n ) \mathcal O(n) O(n)。
#include
using namespace std;
typedef long long ll;
#define int long long
#define ha putchar(' ')
#define he putchar('\n')
inline int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void write(int x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
const int _ = 705;
int n, m, cnt, ans, t[3], c[_], t1[_], t2[_];
bool mp[_][_], f[_][_];
int tot, head[_], to[_ * _], nxt[_ * _];
void add(int u, int v) {
to[++tot] = v, nxt[tot] = head[u], head[u] = tot;
to[++tot] = u, nxt[tot] = head[v], head[v] = tot;
}
void dfs(int u) {
t[c[u]]++;
for (int i = head[u]; i; i = nxt[i]) {
int v = to[i];
if (c[v]) {
if (c[u] == c[v]) {
write(-1);
exit(0);
}
continue;
}
c[v] = (c[u] == 1 ? 2 : 1);
dfs(v);
}
}
signed main() {
n = read(), m = read(), ans = n * n;
for (int i = 1, u, v; i <= m; ++i) {
u = read(), v = read();
mp[u][v] = mp[v][u] = 1;
}
for (int i = 1; i <= n; ++i)
for (int j = i + 1; j <= n; ++j)
if (!mp[i][j]) add(i, j);
for (int i = 1; i <= n; ++i)
if (!c[i]) {
cnt++, c[i] = 1, t[1] = t[2] = 0;
dfs(i);
t1[cnt] = t[1], t2[cnt] = t[2];
}
f[0][0] = 1;
for (int i = 1; i <= cnt; ++i)
for (int j = 0; j <= n; ++j)
if (f[i - 1][j])
f[i][j + t1[i]] = f[i][j + t2[i]] = 1;
for (int i = 0; i <= n; ++i)
if (f[cnt][i]) ans = min(ans, i * (i - 1) / 2 + (n - i) * (n - i - 1) / 2);
write(ans), he;
return 0;
}