最大团 / 独立集
liangbowen · · 题解
写了写发现 TLE 了,然后发现自己居然不会
这里就只写最大团了,反正两者本质相同。
首先有一个
写出代码发现唯一瓶颈是求
这样直接递推
顺带一提,有一个经典题目 qoj7514 Clique Challenge,可以使复杂度与
upd:一个可爱的女孩子让我放个代码,那就放吧:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define mems(x, v) memset(x, v, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef pair <int, int> pii;
typedef long long ll;
typedef unsigned long long ull;
typedef long double wisdom;
int n, m, popc[1 << 25], to[1 << 25], lg[1 << 25]; pair <int, ll> f[1 << 25]; ll E[55]; bool e[55][55], g[1 << 25];
void solve() {
int mid = n / 2;
for (int i = 1; i <= n; i++) e[i][i] = true, E[i] = 0;
for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) if (e[i][j]) E[i] |= (1ll << (j - 1));
for (int S = 0; S < (1 << mid); S++) f[S] = {0, 0}, g[S] = false;
f[0] = {0, 1};
for (int S = 1; S < (1 << mid); S++) {
pair <int, ll> A = f[S ^ (S & -S)], B = f[(S ^ (S & -S)) & E[lg[S & -S]]];
B.first |= (S & -S);
if (popc[B.first] > popc[A.first]) A = B; else if (popc[B.first] == popc[A.first]) A.second += B.second;
f[S] = A;
}
g[0] = true;
for (int S = 1; S < (1 << (n - mid)); S++) {
g[S] = g[S ^ (S & -S)] && !(S & ~(E[lg[S & -S] + mid] >> mid));
}
ll ans = 0, state = 0, tot = 0;
for (int T = 0; T < (1 << (n - mid)); T++) if (g[T]) {
// for (int i = 1; i <= n - mid; i++) if (T >> (i - 1) & 1) S &= E[i + mid];
int S; to[T] = S = (!T ? (1 << mid) - 1 : to[T ^ (T & -T)] & E[lg[T & -T] + mid]);
ll pc = popc[f[S].first] + popc[T], me = f[S].first | ((ll)T << mid);
if (pc > ans) ans = pc, state = me, tot = f[S].second;
else if (pc == ans) tot += f[S].second;
}
cout << ans << ' ' << tot << '\n';
for (int i = 1; i <= n; i++) if (state >> (i - 1) & 1) cout << i << ' ';
cout << '\n';
}
int main() {
cin >> n >> m;
for (int i = 1; i < (1 << ((n + 1) / 2)); i++) popc[i] = popc[i ^ (i & -i)] + 1;
for (int i = 0; i < 25; i++) lg[1 << i] = i + 1;
while (m--) {int u, v; cin >> u >> v; e[u][v] = e[v][u] = true;}
solve(); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) e[i][j] ^= 1; solve();
return 0;
}