const int N = 20;
int с[N]; // с[v] -- соседи v
bool is[1 << N]; // is[A] -- можно ли мн-во A покрасить в один цвет
int bit = 0;
is[0] = 1;
for (int i = 1; i < (1 << N); i++) { // O(2^N)
if ((1 << (bit + 1)) <= i) // bit = max число : 2^{bit} <= i
bit++;
is[i] = is[i ^ (1 << bit)] && ~(i & c[bit]);
}
int f[1 << N]; // min количество цветов нужно чтобы покрасить A
f[0] = 0;
for (int i = 1; i < (1 << N); i++) { // O(4^N)
f[i] = N;
for (int j = 0; j < (1 << N); j++) // O(2^N)
if ((i & j) == j && is[j]) // j -- подмн-во i
f[i] = min(f[i], f[i ^ j] + 1);
}
int f[1 << N]; // min количество цветов нужно чтобы покрасить A
f[0] = 0;
for (int i = 1; i < (1 << N); i++) { // O(3^N)
f[i] = N;
for (int j = i; j > 0; j--, j &= i) // j, i & ~j, ~i
if (is[j]) // j -- подмн-во i
f[i] = min(f[i], f[i ^ j] + 1);
// optimize : j -- макс по включению
// j & (1 << bit) == 0
// is[j ^ (1 << bit)] == 1 => j не нужно рассматривать
// O(2.44^N) 2.44 = 1 + 3^{1/3}
}
// надмножества
for (int j = i; j < (1 << n); j++, j |= i)
;
int w[N];
bool is[1 << N]; // is[j] = (sum[j] <= W)
int f[1 << N]; // f[A] -- мин число заходов
f[0] = 0;
for (int i = 1; i < (1 << N); i++) { // O(3^N)
f[i] = N;
for (int j = i; j > 0; j--, j &= i) // j, i & ~j, ~i
if (is[j]) // j -- подмн-во i
f[i] = min(f[i], f[i ^ j] + 1);
}
// w[0], ... w[n-1], sum = W, sum всех = 2*W, W -- размер рюкзака