int main() {
int n = 10;
int a[n];
int bit_n[1 << n]; // n-bit numbers
bit_n[0] = 0;
for (int i = 1; i < (1 << n); i++)
bit_n[i] = bit_n[i >> 1] + (i & 1);
int upper[1 << n]; // n-bit numbers
upper[0] = -1;
for (int i = 1; i < (1 << n); i++)
upper[i] = upper[i >> 1] + 1;
int sum[1 << n]; // n-bit numbers
sum[0] = 0;
for (int i = 1; i < (1 << n); i++)
sum[i] = sum[i ^ (1 << upper[i])] + a[upper[i]];
/** Time(n) = 2^n, n <= 40 */
/**
if A is proper subset of B then A < B
*/
long long adjacentSet[vertexN];
// adjacentSet[v] -- множество смежных с v вершин
// vertexN <= 64
$\forall$ setOfVertices
isIndependentSet[setOfVertices]
bool isIndependentSet[1 << vertexN];
isIndependentSet[0] = 1;
for (int p = 1; p < (1 << vertexN); p++)
isIndependentSet[p] =
isIndependentSet[p ^ upper[p]] &&
(adjacentSet[upper[p]] & p) == 0;
/** Time = O(2^vertexN) */
/**
объединение = A | B
пересечение = A & B
разность = A & ~B
*/
/** Гамильтонов путь -> Гамильтонов цикл -> Коммивояжёр */
/** Гамильтонов путь */
// O(n!)
// O(2^n * n^2) --> O(2^n * n)
// isPath[setOfVertices, lastVertex] = 0 or 1
int n = vertexN;
bool isPath[1 << n][n];
for (int v = 0; v < n; v++)
isPath[1 << v][v] = 1;
for (int p = 0; p < (1 << n); p++)
for (int last = 0; last < n; last++)
if (isPath[p][last])
for (int next = 0; next < n; next++)
if (isEdge[last][next]) // матрица смежности
isPath[p | (1 << next)][next] = 1;
bool result = 0;
for (int last = 0; last < n; last++)
result |= isPath[(1 << n) - 1][last];
/*** optimize #1 */
int n = vertexN;
int possibleEnds[1 << n];
for (int v = 0; v < n; v++)
possibleEnds[1 << v] = 1 << v;
for (int p = 0; p < (1 << n); p++)
for (int last = 0; last < n; last++)
if ((possibleEnds[p] >> last) & 1)
for (int next = 0; next < n; next++)
if (isEdge[last][next]) // матрица смежности
isPath[p | (1 << next)] |= 1 << next;
/*** optimize #2 */
int n = vertexN;
int possibleEnds[1 << n];
for (int v = 0; v < n; v++)
possibleEnds[1 << v] = 1 << v;
for (int p = 0; p < (1 << n); p++)
for (int next = 0; next < n; next++)
if (possibleEnds[p] & adjacentSet[next])
isPath[p | (1 << next)] |= 1 << next;
}