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 -- размер рюкзака