#include <bits/stdc++.h>
using namespace std;

struct CNF {
    int n = 0, m = 0;
    vector<vector<int>> clauses;
};

static CNF read_cnf(const string& path) {
    FILE* f = fopen(path.c_str(), "r");
    if (!f) { perror(path.c_str()); exit(2); }
    CNF cnf;
    char buf[1 << 20];
    vector<int> cur;
    while (fgets(buf, sizeof(buf), f)) {
        if (buf[0] == 'c' || buf[0] == '\n') continue;
        if (buf[0] == 'p') {
            char tmp[16];
            sscanf(buf, "p %15s %d %d", tmp, &cnf.n, &cnf.m);
            continue;
        }
        char* p = buf;
        while (*p) {
            while (*p && isspace((unsigned char)*p)) ++p;
            if (!*p) break;
            char* e = nullptr;
            long x = strtol(p, &e, 10);
            p = e;
            if (x == 0) {
                if (!cur.empty()) {
                    cnf.clauses.push_back(cur);
                    cur.clear();
                }
            } else {
                cur.push_back((int)x);
            }
        }
    }
    if (!cur.empty()) cnf.clauses.push_back(cur);
    fclose(f);
    return cnf;
}

static long long comb3(long long x) { return x * (x - 1) * (x - 2) / 6; }

static bool gate3(const vector<vector<int>>& c, int i, int& a, int& b, int& d) {
    if (i + 2 >= (int)c.size()) return false;
    const auto &c1 = c[i], &c2 = c[i+1], &c3 = c[i+2];
    if (c1.size() != 3 || c2.size() != 3 || c3.size() != 3) return false;
    a = -c1[0]; b = -c1[1]; d = c1[2];
    return a > 0 && b > 0 && d > 0 &&
           c2[0] == -a && c2[1] == b && c2[2] == -d &&
           c3[0] == a && c3[1] == -b && c3[2] == -d;
}

struct PairMap {
    int M = 0, P = 0, gate_count = 0;
    vector<pair<int,int>> var_pair;
    vector<vector<int>> pair_var;
};

static PairMap infer_pairs(const CNF& cnf) {
    int gc = 0, a, b, d;
    while (gate3(cnf.clauses, gc * 3, a, b, d)) ++gc;
    int M = 0;
    for (int x = 3; x <= 2000; ++x) if (comb3(x) == gc) { M = x; break; }
    if (!M) return {};
    int P = M * (M - 1) / 2;
    PairMap pm;
    pm.M = M; pm.P = P; pm.gate_count = gc;
    pm.var_pair.assign(P + 1, {-1, -1});
    pm.pair_var.assign(M, vector<int>(M, 0));
    auto setp = [&](int v, int i, int j) {
        if (v <= 0 || v > P || i == j) return;
        if (i > j) swap(i, j);
        pm.var_pair[v] = {i, j};
        pm.pair_var[i][j] = pm.pair_var[j][i] = v;
    };
    setp(1, 0, 1);
    vector<int> y0(M, 0);
    y0[1] = 1;
    for (int off = 0; off < M - 2; ++off) {
        gate3(cnf.clauses, off * 3, a, b, d);
        int j = off + 2;
        y0[j] = b;
        setp(b, 0, j);
        setp(d, 1, j);
    }
    vector<int> idx_of_y0(P + 1, -1);
    for (int i = 1; i < M; ++i) idx_of_y0[y0[i]] = i;
    for (int gi = 0; gi < gc; ++gi) {
        gate3(cnf.clauses, gi * 3, a, b, d);
        if (a <= P && b <= P && idx_of_y0[a] >= 0 && idx_of_y0[b] >= 0) {
            int i = idx_of_y0[a], j = idx_of_y0[b];
            if (i < j && !pm.pair_var[i][j]) setp(d, i, j);
        }
    }
    for (int v = 1; v <= P; ++v) if (pm.var_pair[v].first < 0) return {};
    return pm;
}

struct State {
    const CNF* cnf;
    const PairMap* pm;
    vector<unsigned char> val;  // 0/1, variable indexed
    vector<int> colors;
    vector<vector<int>> occ;
    vector<unsigned short> satcnt;
    vector<int> unsat, pos_unsat;
    mt19937_64 rng;
    int alpha = 4;

    bool lit_sat(int lit) const {
        bool v = val[abs(lit)];
        return lit > 0 ? v : !v;
    }

    void add_unsat(int ci) {
        if (pos_unsat[ci] >= 0) return;
        pos_unsat[ci] = (int)unsat.size();
        unsat.push_back(ci);
    }
    void remove_unsat(int ci) {
        int p = pos_unsat[ci];
        if (p < 0) return;
        int last = unsat.back();
        unsat[p] = last;
        pos_unsat[last] = p;
        unsat.pop_back();
        pos_unsat[ci] = -1;
    }
    void update_clause_after_var_change(int ci, bool before_sat, bool after_sat, int delta_satcnt) {
        satcnt[ci] = (unsigned short)((int)satcnt[ci] + delta_satcnt);
        if (before_sat && !after_sat) add_unsat(ci);
        else if (!before_sat && after_sat) remove_unsat(ci);
    }
    void flip_var(int v) {
        bool oldv = val[v];
        for (int ci : occ[v]) {
            bool before = satcnt[ci] > 0;
            int delta = 0;
            for (int lit : cnf->clauses[ci]) if (abs(lit) == v) {
                bool was = lit > 0 ? oldv : !oldv;
                bool now = lit > 0 ? !oldv : oldv;
                delta += (int)now - (int)was;
            }
            bool after = ((int)satcnt[ci] + delta) > 0;
            update_clause_after_var_change(ci, before, after, delta);
        }
        val[v] = !oldv;
    }
    int score_flip_var(int v) {
        bool oldv = val[v];
        int score = 0;
        for (int ci : occ[v]) {
            bool before = satcnt[ci] > 0;
            int delta = 0;
            for (int lit : cnf->clauses[ci]) if (abs(lit) == v) {
                bool was = lit > 0 ? oldv : !oldv;
                bool now = lit > 0 ? !oldv : oldv;
                delta += (int)now - (int)was;
            }
            bool after = ((int)satcnt[ci] + delta) > 0;
            score += (int)after - (int)before;
        }
        return score;
    }
    vector<int> vars_for_color_change(int p, int nc) const {
        vector<int> vars;
        for (int q = 0; q < pm->M; ++q) if (q != p) {
            int v = pm->pair_var[p][q];
            bool nv = (nc == colors[q]);
            if ((bool)val[v] != nv) vars.push_back(v);
        }
        return vars;
    }
    int score_color_change(int p, int nc) {
        auto vars = vars_for_color_change(p, nc);
        if (vars.empty()) return -1000000000;
        unordered_map<int,int> delta;
        delta.reserve(vars.size() * 32);
        int score = 0;
        for (int v : vars) {
            bool oldv = val[v];
            for (int ci : occ[v]) {
                int dlt = 0;
                for (int lit : cnf->clauses[ci]) if (abs(lit) == v) {
                    bool was = lit > 0 ? oldv : !oldv;
                    bool now = lit > 0 ? !oldv : oldv;
                    dlt += (int)now - (int)was;
                }
                delta[ci] += dlt;
            }
        }
        for (auto [ci, dlt] : delta) {
            bool before = satcnt[ci] > 0;
            bool after = ((int)satcnt[ci] + dlt) > 0;
            score += (int)after - (int)before;
        }
        return score;
    }
    void apply_color_change(int p, int nc) {
        auto vars = vars_for_color_change(p, nc);
        for (int v : vars) flip_var(v);
        colors[p] = nc;
    }
    void recompute_sat() {
        int C = cnf->clauses.size();
        satcnt.assign(C, 0);
        unsat.clear();
        pos_unsat.assign(C, -1);
        for (int ci = 0; ci < C; ++ci) {
            int c = 0;
            for (int lit : cnf->clauses[ci]) c += lit_sat(lit);
            satcnt[ci] = c;
            if (!c) add_unsat(ci);
        }
    }
    void init(const CNF& c, const PairMap& pmap, uint64_t seed, int a) {
        cnf = &c; pm = &pmap; alpha = a; rng.seed(seed);
        val.assign(c.n + 1, 0);
        colors.resize(pm->M);
        for (int i = 0; i < pm->M; ++i) colors[i] = (int)(rng() % alpha);
        for (int v = 1; v <= pm->P; ++v) {
            auto [i, j] = pm->var_pair[v];
            val[v] = colors[i] == colors[j];
        }
        for (int v = pm->P + 1; v <= c.n; ++v) val[v] = (rng() >> 8) & 1;
        occ.assign(c.n + 1, {});
        for (int ci = 0; ci < (int)c.clauses.size(); ++ci)
            for (int lit : c.clauses[ci])
                occ[abs(lit)].push_back(ci);
        recompute_sat();
    }
};

int main(int argc, char** argv) {
    if (argc < 3) {
        fprintf(stderr, "usage: sls_solver formula.cnf seconds [seed]\n");
        return 2;
    }
    string path = argv[1];
    double seconds = atof(argv[2]);
    uint64_t seed0 = argc > 3 ? strtoull(argv[3], nullptr, 10) : 1;
    CNF cnf = read_cnf(path);
    PairMap pm = infer_pairs(cnf);
    if (!pm.M) { fprintf(stderr, "detect failed\n"); return 2; }
    fprintf(stderr, "n=%d clauses=%zu M=%d P=%d\n", cnf.n, cnf.clauses.size(), pm.M, pm.P);
    auto deadline = chrono::steady_clock::now() + chrono::duration<double>(seconds);
    vector<int> alphabets = {2,3,4,5,6,8};
    long long total_steps = 0;
    for (int restart = 0; chrono::steady_clock::now() < deadline; ++restart) {
        int alpha = alphabets[restart % alphabets.size()];
        State st;
        st.init(cnf, pm, seed0 + restart * 1000003ull, alpha);
        int best = st.unsat.size();
        for (int step = 0; step < 2000000 && chrono::steady_clock::now() < deadline; ++step, ++total_steps) {
            if (st.unsat.empty()) {
                printf("SAT\n");
                for (int v = 1; v <= cnf.n; ++v) printf("%s%d", v == 1 ? "" : " ", st.val[v] ? v : -v);
                printf(" 0\n");
                fprintf(stderr, "solved restart=%d step=%d total=%lld alpha=%d\n", restart, step, total_steps, alpha);
                return 0;
            }
            if ((int)st.unsat.size() < best) {
                best = st.unsat.size();
                if (best < 20 || step % 50000 == 0)
                    fprintf(stderr, "restart %d alpha %d step %d unsat %d\n", restart, alpha, step, best);
            }
            int ci = st.unsat[st.rng() % st.unsat.size()];
            const auto& cl = cnf.clauses[ci];
            bool moved = false;
            if ((st.rng() & 1023) == 0) {
                int p = st.rng() % pm.M;
                int nc = st.rng() % st.alpha;
                if (nc != st.colors[p]) { st.apply_color_change(p, nc); moved = true; }
            }
            if (moved) continue;
            int best_score = -1000000000, best_aux = 0, best_p = -1, best_c = -1;
            if ((st.rng() % 100) < 8) {
                vector<int> cand;
                for (int lit : cl) if (abs(lit) > pm.P) cand.push_back(abs(lit));
                if (!cand.empty()) {
                    st.flip_var(cand[st.rng() % cand.size()]);
                    continue;
                }
            }
            for (int lit : cl) {
                int v = abs(lit);
                if (v > pm.P) {
                    int sc = st.score_flip_var(v);
                    if (sc > best_score) best_score = sc, best_aux = v, best_p = -1;
                } else {
                    auto [i, j] = pm.var_pair[v];
                    bool want = lit > 0;
                    if (want) {
                        int sc1 = st.score_color_change(i, st.colors[j]);
                        if (sc1 > best_score) best_score = sc1, best_aux = 0, best_p = i, best_c = st.colors[j];
                        int sc2 = st.score_color_change(j, st.colors[i]);
                        if (sc2 > best_score) best_score = sc2, best_aux = 0, best_p = j, best_c = st.colors[i];
                    } else {
                        for (int t = 0; t < 2; ++t) {
                            int p = t ? j : i;
                            int other = t ? i : j;
                            int nc = st.rng() % st.alpha;
                            if (nc == st.colors[other]) nc = (nc + 1) % st.alpha;
                            if (nc == st.colors[p]) continue;
                            int sc = st.score_color_change(p, nc);
                            if (sc > best_score) best_score = sc, best_aux = 0, best_p = p, best_c = nc;
                        }
                    }
                }
            }
            if (best_aux) st.flip_var(best_aux);
            else if (best_p >= 0) st.apply_color_change(best_p, best_c);
            else {
                int lit = cl[st.rng() % cl.size()];
                if (abs(lit) > pm.P) st.flip_var(abs(lit));
            }
        }
        fprintf(stderr, "restart %d ended best/current %d/%zu\n", restart, best, st.unsat.size());
    }
    fprintf(stderr, "UNKNOWN total_steps=%lld\n", total_steps);
    return 1;
}
