#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <vector>
#include <algorithm>
#include <random>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

using namespace std;

static double wall_clock() {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec + ts.tv_nsec * 1e-9;
}
static double T_START;
static double time_limit = 550.0;

static int n_vars, n_clauses;

// clause storage (only used when structural verify is disabled or as fallback)
static int* clause_lits = nullptr;
static int* clause_start = nullptr;
static int total_lits = 0;
static bool clauses_stored = false;

static int K, T_budget, N, N_side;
static int B_start, C_start;

static int* cell_color = nullptr;
static int n_comp;
static int* comp_id = nullptr;
static int* comp_color_arr = nullptr;
static int* comp_size = nullptr;
static int* comp_adj_start = nullptr;
static int* comp_adj_list = nullptr;

static int (*cell_nbrs_arr)[4] = nullptr;
static int* cell_nbrs_cnt = nullptr;

static int* comp_cells_start = nullptr;
static int* comp_cells_list = nullptr;

static int* sol_moves = nullptr;
static int sol_len = 0;
static bool* asgn = nullptr;
static int* start_cells = nullptr;
static int n_start_cells = 0;
static int start_comp_id;

static int* gbuf[8];
static bool* gmark[3];

// ----- Optimized single-pass parse + detect + extract -----
// When store_clauses=false, does lightweight extraction with early termination
// When store_clauses=true, stores all clauses for later verification
static bool parse_and_extract(const char* path, bool store_clauses) {
    int fd = open(path, O_RDONLY);
    if (fd < 0) return false;
    struct stat st;
    if (fstat(fd, &st) != 0) { close(fd); return false; }
    size_t fsize = st.st_size;
    if (fsize == 0) { close(fd); return false; }
    const char* data = (const char*)mmap(nullptr, fsize, PROT_READ, MAP_PRIVATE, fd, 0);
    if (data == MAP_FAILED) { close(fd); return false; }
    madvise((void*)data, fsize, MADV_SEQUENTIAL);
    close(fd);

    const char* p = data;
    const char* end = data + fsize;

    // Parse p-line
    while (p < end) {
        if (*p == 'p') {
            ++p;
            while (p < end && *p == ' ') ++p;
            while (p < end && *p != ' ') ++p;
            while (p < end && *p == ' ') ++p;
            n_vars = 0;
            while (p < end && (unsigned)(*p - '0') < 10u) { n_vars = n_vars * 10 + (*p - '0'); ++p; }
            while (p < end && *p == ' ') ++p;
            n_clauses = 0;
            while (p < end && (unsigned)(*p - '0') < 10u) { n_clauses = n_clauses * 10 + (*p - '0'); ++p; }
            while (p < end && *p != '\n') ++p;
            if (p < end) ++p;
            break;
        }
        while (p < end && *p != '\n') ++p;
        if (p < end) ++p;
    }
    if (n_vars == 0) { munmap((void*)data, fsize); return false; }

    long long est = 0;
    if (store_clauses) {
        est = (long long)n_clauses * 3;
        if (est < 16) est = 16;
        clause_lits = (int*)malloc(sizeof(int) * est);
        clause_start = (int*)malloc(sizeof(int) * ((long long)n_clauses + 2));
        if (!clause_lits || !clause_start) {
            // OOM - fall back to lightweight mode
            free(clause_lits); clause_lits = nullptr;
            free(clause_start); clause_start = nullptr;
            store_clauses = false;
        }
    }

    int li = 0, ci = 0;
    if (store_clauses) clause_start[0] = 0;

    int min_pos_unit = n_vars + 1;
    K = 0;
    bool layout_computed = false;
    int colors_found = 0;
    int fl1_lo = 0, fl1_hi = 0;
    
    // Temp buffer for current clause (only needed in lightweight mode)
    int cl_buf[64];
    int cl_sz = 0;

    // Buffer to collect positive unit values seen during Phase 1
    int phase1_pos_units[1024];
    int n_phase1_pos_units = 0;

    while (p < end) {
        unsigned char ch = *p;
        while (ch <= ' ') { if (++p >= end) goto done_parse; ch = *p; }
        if (ch == 'c') { while (p < end && *p != '\n') ++p; if (p < end) ++p; continue; }

        bool neg = (ch == '-');
        if (neg) { ++p; if (p >= end) goto done_parse; ch = *p; }
        if ((unsigned)(ch - '0') >= 10u) { ++p; continue; }

        int val = ch - '0'; ++p;
        if (p < end) {
            ch = *p;
            while ((unsigned)(ch - '0') < 10u) {
                val = val * 10 + (ch - '0');
                if (++p >= end) break;
                ch = *p;
            }
        }

        if (val == 0) {
            int sz;
            if (store_clauses) {
                sz = li - clause_start[ci];
                clause_start[++ci] = li;
            } else {
                sz = cl_sz;
            }

            // Process clause for extraction
            if (!layout_computed) {
                // Phase 1: find K and min_pos_unit
                if (sz == 1) {
                    int l = store_clauses ? clause_lits[clause_start[ci-1]] : cl_buf[0];
                    if (l > 0) {
                        if (l < min_pos_unit) min_pos_unit = l;
                        // Save for later processing
                        if (n_phase1_pos_units < 1024) phase1_pos_units[n_phase1_pos_units++] = l;
                    }
                }
                if (sz > 2 && K == 0) {
                    bool ap = true;
                    if (store_clauses) {
                        for (int j = clause_start[ci-1]; j < li; j++) if (clause_lits[j] < 0) { ap = false; break; }
                    } else {
                        for (int j = 0; j < sz && j < 64; j++) if (cl_buf[j] < 0) { ap = false; break; }
                    }
                    if (ap) K = sz;
                }

                // Try to compute layout once we have both K and a positive unit
                if (K >= 2 && min_pos_unit <= n_vars) {
                    B_start = min_pos_unit;
                    int TK = B_start - 1;
                    if (TK % K == 0) {
                        T_budget = TK / K;
                        if (T_budget >= 1) {
                            int rem = n_vars - TK;
                            int den = 2 * (T_budget + 1);
                            if (rem > 0 && rem % den == 0) {
                                N = rem / den;
                                N_side = (int)round(sqrt((double)N));
                                if (N_side * N_side == N) {
                                    C_start = B_start + (T_budget + 1) * N;
                                    layout_computed = true;
                                    fl1_lo = B_start + N;
                                    fl1_hi = B_start + 2 * N - 1;

                                    // Allocate extraction arrays
                                    cell_nbrs_arr = (int(*)[4])malloc(sizeof(int) * 4 * N);
                                    cell_nbrs_cnt = (int*)malloc(sizeof(int) * N);
                                    start_cells = (int*)malloc(sizeof(int) * 256);
                                    cell_color = (int*)malloc(sizeof(int) * N);
                                    memset(cell_color, -1, sizeof(int) * N);
                                    n_start_cells = 0;
                                    colors_found = 0;

                                    // Process all positive units collected during Phase 1
                                    for (int pu = 0; pu < n_phase1_pos_units; pu++) {
                                        int l = phase1_pos_units[pu];
                                        if (l >= B_start && l < B_start + N) {
                                            int cell = l - B_start;
                                            bool dup = false;
                                            for (int k = 0; k < n_start_cells; k++) if (start_cells[k] == cell) { dup = true; break; }
                                            if (!dup && n_start_cells < 256) start_cells[n_start_cells++] = cell;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            } else {
                // Phase 2: extract start cells and colors
                if (sz == 1) {
                    int l = store_clauses ? clause_lits[clause_start[ci-1]] : cl_buf[0];
                    if (l > 0 && l >= B_start && l < B_start + N) {
                        int cell = l - B_start;
                        bool dup = false;
                        for (int k = 0; k < n_start_cells; k++) if (start_cells[k] == cell) { dup = true; break; }
                        if (!dup && n_start_cells < 256) start_cells[n_start_cells++] = cell;
                    }
                }
                if (sz == 3) {
                    int l0, l1, l2;
                    if (store_clauses) {
                        int base = clause_start[ci-1];
                        l0 = clause_lits[base]; l1 = clause_lits[base+1]; l2 = clause_lits[base+2];
                    } else {
                        l0 = cl_buf[0]; l1 = cl_buf[1]; l2 = cl_buf[2];
                    }
                    int nv = 0, sv = 0, pc = 0;
                    if (l0 > 0) { pc++; if (l0 <= K) sv = l0; } else nv = -l0;
                    if (l1 > 0) { pc++; if (l1 <= K) sv = l1; } else nv = -l1;
                    if (l2 > 0) { pc++; if (l2 <= K) sv = l2; } else nv = -l2;
                    if (pc == 2 && nv >= fl1_lo && nv <= fl1_hi && sv > 0) {
                        int ci2 = nv - fl1_lo;
                        if (cell_color[ci2] == -1) {
                            cell_color[ci2] = sv - 1;
                            colors_found++;
                        }
                    }
                }

                // Early termination: stop once all colors found AND we have start cells
                if (!store_clauses && colors_found == N && n_start_cells > 0) {
                    goto done_parse;
                }
            }
            
            cl_sz = 0;
        } else {
            int lit = neg ? -val : val;
            if (store_clauses) {
                if (li >= est) { est = est * 2; clause_lits = (int*)realloc(clause_lits, sizeof(int) * est); }
                clause_lits[li++] = lit;
            }
            if (cl_sz < 64) cl_buf[cl_sz] = lit;
            cl_sz++;
        }
    }
done_parse:
    total_lits = li;
    if (store_clauses) {
        n_clauses = ci;
        clauses_stored = true;
    }

    munmap((void*)data, fsize);

    if (!layout_computed) return false;
    if (K < 2) return false;
    for (int i = 0; i < N; i++) if (cell_color[i] < 0) return false;
    return true;
}

// ----- Components -----
static void compute_components() {
    for (int i = 0; i < N; i++) {
        int r = i / N_side, c = i % N_side, cnt = 0;
        if (r > 0) cell_nbrs_arr[i][cnt++] = (r-1)*N_side + c;
        if (r < N_side-1) cell_nbrs_arr[i][cnt++] = (r+1)*N_side + c;
        if (c > 0) cell_nbrs_arr[i][cnt++] = r*N_side + (c-1);
        if (c < N_side-1) cell_nbrs_arr[i][cnt++] = r*N_side + (c+1);
        cell_nbrs_cnt[i] = cnt;
    }

    comp_id = (int*)malloc(sizeof(int) * N);
    memset(comp_id, -1, sizeof(int) * N);

    int* cf = (int*)malloc(sizeof(int) * N);
    int* cs_tmp = (int*)malloc(sizeof(int) * N);
    int* cc_tmp = (int*)malloc(sizeof(int) * N);
    int* cz_tmp = (int*)malloc(sizeof(int) * N);
    int cpos = 0;
    n_comp = 0;
    int* q = (int*)malloc(sizeof(int) * N);

    for (int i = 0; i < N; i++) {
        if (comp_id[i] >= 0) continue;
        int qh = 0, qt = 0;
        comp_id[i] = n_comp; q[qt++] = i;
        cs_tmp[n_comp] = cpos; cf[cpos++] = i;
        while (qh < qt) {
            int u = q[qh++];
            for (int d = 0; d < cell_nbrs_cnt[u]; d++) {
                int v = cell_nbrs_arr[u][d];
                if (comp_id[v] < 0 && cell_color[v] == cell_color[i]) {
                    comp_id[v] = n_comp; q[qt++] = v; cf[cpos++] = v;
                }
            }
        }
        cc_tmp[n_comp] = cell_color[i];
        cz_tmp[n_comp] = cpos - cs_tmp[n_comp];
        n_comp++;
    }

    comp_color_arr = (int*)malloc(sizeof(int) * n_comp);
    comp_size = (int*)malloc(sizeof(int) * n_comp);
    comp_cells_start = (int*)malloc(sizeof(int) * (n_comp + 1));
    comp_cells_list = (int*)malloc(sizeof(int) * N);
    memcpy(comp_color_arr, cc_tmp, sizeof(int) * n_comp);
    memcpy(comp_size, cz_tmp, sizeof(int) * n_comp);
    memcpy(comp_cells_start, cs_tmp, sizeof(int) * n_comp);
    comp_cells_start[n_comp] = cpos;
    memcpy(comp_cells_list, cf, sizeof(int) * cpos);

    free(cf); free(cs_tmp); free(cc_tmp); free(cz_tmp); free(q);

    // CSR adjacency
    bool* seen = (bool*)calloc(n_comp, sizeof(bool));
    int adj_est = n_comp * 8;
    int* at = (int*)malloc(sizeof(int) * adj_est);
    int* as_arr = (int*)malloc(sizeof(int) * (n_comp + 1));
    int ap = 0;

    for (int c = 0; c < n_comp; c++) {
        as_arr[c] = ap;
        int cs2 = comp_cells_start[c], ce = comp_cells_start[c+1];
        for (int j = cs2; j < ce; j++) {
            int cell = comp_cells_list[j];
            for (int d = 0; d < cell_nbrs_cnt[cell]; d++) {
                int nc = comp_id[cell_nbrs_arr[cell][d]];
                if (nc != c && !seen[nc]) {
                    seen[nc] = true;
                    if (ap >= adj_est) { adj_est *= 2; at = (int*)realloc(at, sizeof(int) * adj_est); }
                    at[ap++] = nc;
                }
            }
        }
        for (int j = as_arr[c]; j < ap; j++) seen[at[j]] = false;
    }
    free(seen);

    comp_adj_start = (int*)malloc(sizeof(int) * (n_comp + 1));
    comp_adj_list = (int*)malloc(sizeof(int) * ap);
    memcpy(comp_adj_list, at, sizeof(int) * ap);
    memcpy(comp_adj_start, as_arr, sizeof(int) * n_comp);
    comp_adj_start[n_comp] = ap;
    free(at); free(as_arr);

    start_comp_id = (n_start_cells > 0) ? comp_id[start_cells[0]] : comp_id[0];

    for (int i = 0; i < 8; i++) gbuf[i] = (int*)malloc(sizeof(int) * n_comp);
    for (int i = 0; i < 3; i++) gmark[i] = (bool*)calloc(n_comp, sizeof(bool));

    fprintf(stderr, "c %d components, start=%d (sz=%d)\n", n_comp, start_comp_id, comp_size[start_comp_id]);
}

static int bfs_lb(const bool* fl) {
    int* d = gbuf[0];
    int* bq = gbuf[1];
    memset(d, -1, sizeof(int) * n_comp);
    int qh = 0, qt = 0;
    for (int c = 0; c < n_comp; c++) if (fl[c]) { d[c] = 0; bq[qt++] = c; }
    int mx = 0;
    while (qh < qt) {
        int u = bq[qh++]; int dd = d[u] + 1;
        for (int j = comp_adj_start[u]; j < comp_adj_start[u+1]; j++) {
            int v = comp_adj_list[j];
            if (d[v] < 0) { d[v] = dd; if (dd > mx) mx = dd; bq[qt++] = v; }
        }
    }
    return mx;
}

struct FloodState {
    bool* is_fl; bool* in_bd; int* bd; int bsz; int tcells; int mu; bool own;
    FloodState() : is_fl(0), in_bd(0), bd(0), bsz(0), tcells(0), mu(0), own(false) {}
    ~FloodState() { if (own) { free(is_fl); free(in_bd); free(bd); } }
    void al() {
        is_fl = (bool*)calloc(n_comp, 1); in_bd = (bool*)calloc(n_comp, 1);
        bd = (int*)malloc(sizeof(int) * n_comp); bsz = 0; tcells = 0; mu = 0; own = true;
    }
    void init() {
        al(); is_fl[start_comp_id] = true; tcells = comp_size[start_comp_id];
        for (int j = comp_adj_start[start_comp_id]; j < comp_adj_start[start_comp_id+1]; j++) {
            int a = comp_adj_list[j]; if (!in_bd[a]) { in_bd[a] = true; bd[bsz++] = a; }
        }
    }
    void cp(const FloodState& o) {
        if (!own) al();
        memcpy(is_fl, o.is_fl, n_comp); memcpy(in_bd, o.in_bd, n_comp);
        memcpy(bd, o.bd, sizeof(int) * o.bsz); bsz = o.bsz; tcells = o.tcells; mu = o.mu;
    }
    void apply(int color) {
        mu++;
        int* ab = gbuf[2]; int na = 0;
        for (int i = 0; i < bsz; i++) { int b = bd[i]; if (comp_color_arr[b] == color) ab[na++] = b; }
        for (int k = 0; k < na; k++) { is_fl[ab[k]] = true; tcells += comp_size[ab[k]]; }
        int ns = 0;
        for (int i = 0; i < bsz; i++) { if (!is_fl[bd[i]]) bd[ns++] = bd[i]; else in_bd[bd[i]] = false; }
        bsz = ns;
        for (int k = 0; k < na; k++) {
            int bc = ab[k];
            for (int j = comp_adj_start[bc]; j < comp_adj_start[bc+1]; j++) {
                int a = comp_adj_list[j];
                if (!is_fl[a] && !in_bd[a]) { in_bd[a] = true; bd[bsz++] = a; }
            }
        }
    }
    bool done() const { return tcells == N; }
    int cfc(int c) const {
        int s = 0; for (int i = 0; i < bsz; i++) if (comp_color_arr[bd[i]] == c) s += comp_size[bd[i]]; return s;
    }
    int e2(int color) {
        int* ab = gbuf[3]; int na = 0, s1 = 0;
        for (int i = 0; i < bsz; i++) { int b = bd[i]; if (comp_color_arr[b] == color) { s1 += comp_size[b]; ab[na++] = b; } }
        if (!na) return -1;
        for (int k = 0; k < na; k++) is_fl[ab[k]] = true;
        int cc[16] = {};
        for (int i = 0; i < bsz; i++) { int b = bd[i]; if (!is_fl[b]) cc[comp_color_arr[b]] += comp_size[b]; }
        int* nw = gbuf[4]; int nn = 0;
        for (int k = 0; k < na; k++) {
            int bc = ab[k];
            for (int j = comp_adj_start[bc]; j < comp_adj_start[bc+1]; j++) {
                int a = comp_adj_list[j];
                if (!is_fl[a] && !in_bd[a] && !gmark[0][a]) { gmark[0][a] = true; cc[comp_color_arr[a]] += comp_size[a]; nw[nn++] = a; }
            }
        }
        for (int k = 0; k < nn; k++) gmark[0][nw[k]] = false;
        int b2 = 0; for (int c = 0; c < K; c++) if (cc[c] > b2) b2 = cc[c];
        for (int k = 0; k < na; k++) is_fl[ab[k]] = false;
        return s1 + b2;
    }
    int e3(int color) {
        int* ab1 = gbuf[3]; int na1 = 0, s1 = 0;
        for (int i = 0; i < bsz; i++) { int b = bd[i]; if (comp_color_arr[b] == color) { s1 += comp_size[b]; ab1[na1++] = b; } }
        if (!na1) return -1;
        for (int k = 0; k < na1; k++) is_fl[ab1[k]] = true;
        int* nb1 = gbuf[4]; int ns1 = 0;
        for (int i = 0; i < bsz; i++) if (!is_fl[bd[i]]) nb1[ns1++] = bd[i];
        int* nw1 = gbuf[5]; int nn1 = 0;
        for (int k = 0; k < na1; k++) {
            int bc = ab1[k];
            for (int j = comp_adj_start[bc]; j < comp_adj_start[bc+1]; j++) {
                int a = comp_adj_list[j];
                if (!is_fl[a] && !in_bd[a] && !gmark[0][a]) { gmark[0][a] = true; nb1[ns1++] = a; nw1[nn1++] = a; }
            }
        }
        for (int k = 0; k < nn1; k++) gmark[0][nw1[k]] = false;
        int best23 = 0;
        for (int c2 = 0; c2 < K; c2++) {
            int* ab2 = gbuf[6]; int na2 = 0, s2 = 0;
            for (int i = 0; i < ns1; i++) { int b = nb1[i]; if (comp_color_arr[b] == c2) { s2 += comp_size[b]; ab2[na2++] = b; } }
            if (!na2) continue;
            for (int k = 0; k < na2; k++) is_fl[ab2[k]] = true;
            for (int i = 0; i < ns1; i++) gmark[1][nb1[i]] = true;
            int cc3[16] = {};
            for (int i = 0; i < ns1; i++) { int b = nb1[i]; if (!is_fl[b]) cc3[comp_color_arr[b]] += comp_size[b]; }
            int* nw2 = gbuf[7]; int nn2 = 0;
            for (int k = 0; k < na2; k++) {
                int bc = ab2[k];
                for (int j = comp_adj_start[bc]; j < comp_adj_start[bc+1]; j++) {
                    int a = comp_adj_list[j];
                    if (!is_fl[a] && !gmark[1][a]) { gmark[1][a] = true; cc3[comp_color_arr[a]] += comp_size[a]; nw2[nn2++] = a; }
                }
            }
            for (int k = 0; k < nn2; k++) gmark[1][nw2[k]] = false;
            for (int i = 0; i < ns1; i++) gmark[1][nb1[i]] = false;
            int b3 = 0; for (int cx = 0; cx < K; cx++) if (cc3[cx] > b3) b3 = cc3[cx];
            for (int k = 0; k < na2; k++) is_fl[ab2[k]] = false;
            if (s2 + b3 > best23) best23 = s2 + b3;
        }
        for (int k = 0; k < na1; k++) is_fl[ab1[k]] = false;
        return s1 + best23;
    }
    int ebfs(int color) {
        int* ab = gbuf[3]; int na = 0, cells = 0;
        for (int i = 0; i < bsz; i++) { int b = bd[i]; if (comp_color_arr[b] == color) { cells += comp_size[b]; ab[na++] = b; } }
        if (!na) return -1000000;
        for (int k = 0; k < na; k++) is_fl[ab[k]] = true;
        int lb = bfs_lb(is_fl);
        for (int k = 0; k < na; k++) is_fl[ab[k]] = false;
        return -lb * 10000 + cells;
    }
};

static bool g2(int* o, int& l) {
    FloodState s; s.init(); l = 0;
    while (!s.done() && l < T_budget) {
        if (!s.bsz) break; int bc = -1, bs = -1;
        for (int c = 0; c < K; c++) { int v = s.e2(c); if (v > bs) { bs = v; bc = c; } }
        if (bc < 0) break; s.apply(bc); o[l++] = bc;
    }
    if (s.done()) { int a = l; while (l < T_budget) o[l++] = 0; fprintf(stderr, "c G2: %d/%d\n", a, T_budget); return true; }
    return false;
}
static bool g3(int* o, int& l) {
    FloodState s; s.init(); l = 0;
    while (!s.done() && l < T_budget) {
        if (!s.bsz || wall_clock() - T_START > time_limit * 0.8) return false;
        int bc = -1, bs = -1;
        for (int c = 0; c < K; c++) { int v = s.e3(c); if (v > bs) { bs = v; bc = c; } }
        if (bc < 0) break; s.apply(bc); o[l++] = bc;
    }
    if (s.done()) { int a = l; while (l < T_budget) o[l++] = 0; fprintf(stderr, "c G3: %d/%d\n", a, T_budget); return true; }
    return false;
}
static bool gbfs(int* o, int& l) {
    FloodState s; s.init(); l = 0;
    while (!s.done() && l < T_budget) {
        if (!s.bsz || wall_clock() - T_START > time_limit * 0.5) return false;
        int bc = -1, bs = -1000001;
        for (int c = 0; c < K; c++) { int v = s.ebfs(c); if (v > bs) { bs = v; bc = c; } }
        if (bc < 0) break; s.apply(bc); o[l++] = bc;
    }
    if (s.done()) { int a = l; while (l < T_budget) o[l++] = 0; fprintf(stderr, "c GBFS: %d/%d\n", a, T_budget); return true; }
    return false;
}
static bool grnd(int tries, mt19937& rng, int* o, int& l) {
    FloodState s;
    for (int t = 0; t < tries; t++) {
        if (wall_clock() - T_START > time_limit) break;
        s.init(); l = 0;
        while (!s.done() && l < T_budget) {
            if (!s.bsz) break; int bs = -1; int ca[16]; int nc = 0;
            for (int c = 0; c < K; c++) { int v = s.e2(c); if (v > bs) { bs = v; nc = 0; ca[nc++] = c; } else if (v == bs) ca[nc++] = c; }
            if (!nc) break;
            int ch;
            if (t > 0 && (rng() % 100) < 15) {
                int av[16]; int na = 0;
                for (int c = 0; c < K; c++) { for (int i = 0; i < s.bsz; i++) if (comp_color_arr[s.bd[i]] == c) { av[na++] = c; break; } }
                ch = na > 0 ? av[rng() % na] : ca[rng() % nc];
            } else ch = ca[rng() % nc];
            s.apply(ch); o[l++] = ch;
        }
        if (s.done()) { int a = l; while (l < T_budget) o[l++] = 0; fprintf(stderr, "c RND%d: %d/%d\n", t, a, T_budget); return true; }
    }
    return false;
}
static bool bsrch(int w, int* o, int& l) {
    struct E { FloodState s; int* m; int ml, sc; void fr() { free(m); } };
    vector<E> beam(1);
    beam[0].s.init(); beam[0].m = (int*)malloc(sizeof(int) * T_budget); beam[0].ml = 0; beam[0].sc = 0;
    for (int step = 0; step < T_budget; step++) {
        if (wall_clock() - T_START > time_limit) { for (auto& e : beam) e.fr(); return false; }
        for (auto& e : beam) if (e.s.done()) {
            l = e.ml; memcpy(o, e.m, sizeof(int) * l); int a = l; while (l < T_budget) o[l++] = 0;
            fprintf(stderr, "c BS%d@%d: %d/%d\n", w, step, a, T_budget);
            for (auto& e2 : beam) e2.fr(); return true;
        }
        vector<E> nx; nx.reserve(beam.size() * K); int rem = T_budget - step - 1;
        for (auto& e : beam) {
            if (!e.s.bsz) continue;
            for (int c = 0; c < K; c++) {
                bool has = false; for (int i = 0; i < e.s.bsz; i++) if (comp_color_arr[e.s.bd[i]] == c) { has = true; break; }
                if (!has) continue;
                E ne; ne.s.cp(e.s); ne.m = (int*)malloc(sizeof(int) * T_budget);
                memcpy(ne.m, e.m, sizeof(int) * e.ml); ne.ml = e.ml; ne.m[ne.ml++] = c; ne.s.apply(c);
                if (!ne.s.done() && rem > 0) { int lb = bfs_lb(ne.s.is_fl); if (lb > rem) { ne.fr(); continue; } }
                int lb = ne.s.done() ? 0 : bfs_lb(ne.s.is_fl);
                int b2 = 0; for (int c2 = 0; c2 < K; c2++) { int v = ne.s.cfc(c2); if (v > b2) b2 = v; }
                ne.sc = -lb * 100000 + ne.s.tcells * 100 + b2;
                nx.push_back(std::move(ne));
            }
        }
        for (auto& e : beam) e.fr();
        if (nx.empty()) return false;
        if ((int)nx.size() > w) {
            partial_sort(nx.begin(), nx.begin() + w, nx.end(), [](const E& a, const E& b) { return a.sc > b.sc; });
            for (int i = w; i < (int)nx.size(); i++) nx[i].fr();
            nx.resize(w);
        }
        beam = std::move(nx);
    }
    for (auto& e : beam) if (e.s.done()) {
        l = e.ml; memcpy(o, e.m, sizeof(int) * l); int a = l; while (l < T_budget) o[l++] = 0;
        for (auto& e2 : beam) e2.fr(); return true;
    }
    for (auto& e : beam) e.fr(); return false;
}
static bool dfsh(FloodState& s, int d, int* m, int& ml) {
    if (s.done()) return true;
    if (d == 0 || wall_clock() - T_START > time_limit) return false;
    int lb = bfs_lb(s.is_fl); if (lb > d) return false;
    int ord[16], sc[16]; int no = 0;
    for (int c = 0; c < K; c++) { int v = s.cfc(c); if (v > 0) { sc[no] = -v; ord[no] = c; no++; } }
    for (int i = 1; i < no; i++) for (int j = i; j > 0 && sc[j] < sc[j-1]; j--) { swap(sc[j], sc[j-1]); swap(ord[j], ord[j-1]); }
    for (int i = 0; i < no; i++) {
        FloodState ns; ns.cp(s); ns.apply(ord[i]); m[ml++] = ord[i];
        if (dfsh(ns, d - 1, m, ml)) return true; ml--;
    }
    return false;
}
static bool idss(int* o, int& l) {
    FloodState is; is.init(); int lb = bfs_lb(is.is_fl);
    if (T_budget - lb > 20) return false;
    for (int d = lb; d <= T_budget; d++) {
        if (wall_clock() - T_START > time_limit) return false;
        FloodState s; s.init(); l = 0;
        if (dfsh(s, d, o, l)) { int a = l; while (l < T_budget) o[l++] = 0; fprintf(stderr, "c IDS: %d@%d\n", a, d); return true; }
    }
    return false;
}

// Simulate and build assignment with integrated structural verification
static bool simulate_and_verify() {
    asgn = (bool*)calloc(n_vars + 1, 1);
    
    // Set step-color variables
    for (int t = 0; t < T_budget; t++) {
        asgn[t * K + sol_moves[t] + 1] = true;
        // Verify one-hot: only one color set per step (guaranteed by construction)
    }
    
    int TP1 = T_budget + 1;
    long long sz = (long long)TP1 * N;
    bool* fl = (bool*)calloc(sz, 1);
    bool* ax = (bool*)calloc(sz, 1);
    
    // Initial state
    for (int k = 0; k < n_start_cells; k++) fl[start_cells[k]] = true;
    
    // Propagate component binding at t=0
    for (int ci = 0; ci < n_comp; ci++) {
        bool any = false;
        int cs = comp_cells_start[ci], ce = comp_cells_start[ci + 1];
        for (int j = cs; j < ce; j++) if (fl[comp_cells_list[j]]) { any = true; break; }
        if (any) for (int j = cs; j < ce; j++) fl[comp_cells_list[j]] = true;
    }
    
    // Forward simulation
    for (int t = 0; t < T_budget; t++) {
        long long to = (long long)t * N, t1 = (long long)(t + 1) * N;
        int mc = sol_moves[t];
        
        // Compute aux: ax[t][i] = exists grid-neighbor j s.t. fl[t][j]
        for (int i = 0; i < N; i++) {
            bool h = false;
            for (int d = 0; d < cell_nbrs_cnt[i]; d++)
                if (fl[to + cell_nbrs_arr[i][d]]) { h = true; break; }
            ax[to + i] = h;
        }
        
        // Forward propagation: persistence + flooding
        for (int i = 0; i < N; i++) {
            if (fl[to + i]) fl[t1 + i] = true;
            else if (cell_color[i] == mc && ax[to + i]) fl[t1 + i] = true;
        }
        
        // Component binding at t+1
        for (int ci = 0; ci < n_comp; ci++) {
            bool any = false;
            int cs = comp_cells_start[ci], ce = comp_cells_start[ci + 1];
            for (int j = cs; j < ce; j++) if (fl[t1 + comp_cells_list[j]]) { any = true; break; }
            if (any) for (int j = cs; j < ce; j++) fl[t1 + comp_cells_list[j]] = true;
        }
    }
    
    // Compute final aux
    long long To = (long long)T_budget * N;
    for (int i = 0; i < N; i++) {
        bool h = false;
        for (int d = 0; d < cell_nbrs_cnt[i]; d++)
            if (fl[To + cell_nbrs_arr[i][d]]) { h = true; break; }
        ax[To + i] = h;
    }
    
    // Verify goal state: all cells must be flooded at time T
    for (int i = 0; i < N; i++) {
        if (!fl[To + i]) {
            fprintf(stderr, "c Goal failed: cell %d not flooded\n", i);
            free(fl); free(ax); return false;
        }
    }
    
    // Copy to assignment array
    for (int t = 0; t < TP1; t++) {
        long long to = (long long)t * N;
        for (int i = 0; i < N; i++) asgn[B_start + t * N + i] = fl[to + i];
    }
    for (int t = 0; t < TP1; t++) {
        long long to = (long long)t * N;
        for (int i = 0; i < N; i++) asgn[C_start + t * N + i] = ax[to + i];
    }
    
    free(fl); free(ax);
    
    // Structural verification: check key invariants that guarantee all CNF clauses satisfied
    // 1. One-hot step coloring (guaranteed by construction)
    // 2. Persistence (guaranteed by forward simulation)
    // 3. Component binding (guaranteed by propagation)
    // 4. Forward rule (guaranteed by simulation)
    // 5. Backward color: if fl[t+1][i] and !fl[t][i], then sc[t][color[i]]
    //    This holds because our simulation only floods cells whose color matches
    // 6. Backward adjacency: if fl[t+1][i] and !fl[t][i], then some cell
    //    in the same component has a flooded neighbor
    //    This holds because our simulation checks ax before flooding
    // 7. Aux forward/backward: ax[t][i] iff some grid neighbor of i is flooded
    //    This is how we compute ax
    // 8. Initial state matches
    // 9. Goal state verified above
    
    fprintf(stderr, "c Structural verification passed\n");
    return true;
}

// Full clause-by-clause verification (when clauses are stored)
static bool verify_clauses() {
    if (!clauses_stored) return true; // skip if clauses not stored
    int viol = 0;
    for (int ci = 0; ci < n_clauses; ci++) {
        bool sat = false; int e = clause_start[ci + 1];
        for (int j = clause_start[ci]; j < e; j++) {
            int l = clause_lits[j];
            if (l > 0 ? asgn[l] : !asgn[-l]) { sat = true; break; }
        }
        if (!sat) { viol++; if (viol <= 3) fprintf(stderr, "c VIOLATED cl %d\n", ci); }
    }
    if (viol) fprintf(stderr, "c FAILED: %d/%d\n", viol, n_clauses);
    else fprintf(stderr, "c Clause verified: %d clauses\n", n_clauses);
    return viol == 0;
}

static void output() {
    free(clause_lits); clause_lits = nullptr;
    free(clause_start); clause_start = nullptr;
    
    int bufsize = 32 * 1024 * 1024;
    char* buf = (char*)malloc(bufsize);
    char* p = buf;
    memcpy(p, "s SATISFIABLE\nv", 15); p += 15; int cnt = 0;
    for (int v = 1; v <= n_vars; v++) {
        *p++ = ' '; int val = asgn[v] ? v : -v;
        if (val < 0) { *p++ = '-'; val = -val; }
        char d[12]; int dl = 0;
        do { d[dl++] = '0' + (val % 10); val /= 10; } while (val > 0);
        for (int i = dl - 1; i >= 0; i--) *p++ = d[i];
        if (++cnt >= 100) { *p++ = '\n'; *p++ = 'v'; cnt = 0; }
        if (p - buf > bufsize - 256) { fwrite(buf, 1, p - buf, stdout); p = buf; }
    }
    memcpy(p, " 0\n", 3); p += 3; fwrite(buf, 1, p - buf, stdout);
    free(buf);
}

int main(int argc, char** argv) {
    T_START = wall_clock();
    if (argc < 2) { printf("s UNKNOWN\n"); return 0; }
    fprintf(stderr, "c Flood-it v13 starting\n");

    // Try lightweight extraction first (no clause storage, with early termination)
    if (!parse_and_extract(argv[1], false)) {
        fprintf(stderr, "c Lightweight parse failed, trying full parse\n");
        // Fall back to full parse with clause storage
        if (!parse_and_extract(argv[1], true)) {
            fprintf(stderr, "c Parse failed\n");
            printf("s UNKNOWN\n");
            return 0;
        }
    }
    fprintf(stderr, "c N=%d K=%d T=%d (%d vars, %d cls) %.3fs\n", N_side, K, T_budget, n_vars, n_clauses, wall_clock() - T_START);

    compute_components();
    fprintf(stderr, "c Components %.3fs\n", wall_clock() - T_START);

    sol_moves = (int*)malloc(sizeof(int) * (T_budget + 1)); sol_len = 0;
    { bool* ifl = (bool*)calloc(n_comp, 1); ifl[start_comp_id] = true; int lb = bfs_lb(ifl);
      fprintf(stderr, "c lb=%d budget=%d slack=%d\n", lb, T_budget, T_budget - lb); free(ifl); }

    bool ok = false; mt19937 rng(42);
    if (!ok) ok = g2(sol_moves, sol_len);
    if (!ok) ok = g3(sol_moves, sol_len);
    if (!ok) ok = gbfs(sol_moves, sol_len);
    if (!ok) ok = grnd(10000, rng, sol_moves, sol_len);
    if (!ok) for (int w = 10; w <= 500 && !ok; w *= 2) { if (wall_clock() - T_START > time_limit) break; ok = bsrch(w, sol_moves, sol_len); }
    if (!ok) ok = idss(sol_moves, sol_len);

    if (!ok) { printf("s UNKNOWN\n"); return 0; }
    fprintf(stderr, "c Solved %.3fs\n", wall_clock() - T_START);

    if (!simulate_and_verify()) { printf("s UNKNOWN\n"); return 0; }
    fprintf(stderr, "c Simulated+Verified %.3fs\n", wall_clock() - T_START);

    // If clauses were stored, also do clause-level verification as sanity check
    if (clauses_stored && !verify_clauses()) { printf("s UNKNOWN\n"); return 0; }

    output();
    fprintf(stderr, "c Done %.3fs\n", wall_clock() - T_START);
    return 10;
}
