#include <algorithm>
#include <chrono>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <deque>
#include <iostream>
#include <limits>
#include <string>
#include <vector>

struct RNG {
    uint64_t s;
    explicit RNG(uint64_t seed = 1) : s(seed ? seed : 1) {}
    uint64_t next() {
        uint64_t x = s;
        x ^= x << 7;
        x ^= x >> 9;
        s = x;
        return x;
    }
    int uniform_int(int n) { return (int)(next() % (uint64_t)n); }
    double unit() { return (next() >> 11) * (1.0 / 9007199254740992.0); }
};

static inline int lidx(int lit) { return (std::abs(lit) << 1) ^ (lit < 0); }

struct Clause {
    int start = 0;
    int size = 0;
    int w0 = 0;
    int w1 = 0;
};

struct Occ {
    int cid;
    signed char sign;  // +1 for positive var literal, -1 for negative.
};

struct Solver {
    int nvars = 0, nclauses = 0;
    std::vector<int> lits;
    std::vector<Clause> clauses;
    std::vector<std::vector<int>> watch;
    std::vector<signed char> bcp_val;
    std::deque<int> q;

    std::vector<signed char> val;
    std::vector<unsigned short> sat_count;
    std::vector<int> unsat;
    std::vector<int> unsat_pos;
    std::vector<int> occ_start;
    std::vector<Occ> occs;
    std::vector<unsigned char> fixed;

    int lit_val_partial(int lit) const {
        signed char x = bcp_val[std::abs(lit)];
        if (!x) return 0;
        return lit > 0 ? x : -x;
    }
    int lit_val_full(int lit) const {
        signed char x = val[std::abs(lit)];
        return lit > 0 ? x : -x;
    }
    bool assign_bcp(int lit) {
        int v = std::abs(lit);
        signed char want = lit > 0 ? 1 : -1;
        if (bcp_val[v] == want) return true;
        if (bcp_val[v] == -want) return false;
        bcp_val[v] = want;
        q.push_back(lit);
        return true;
    }
    bool read_dimacs(const char* path) {
        FILE* f = std::fopen(path, "r");
        if (!f) {
            std::perror(path);
            return false;
        }
        char ch;
        while ((ch = std::getc(f)) != EOF) {
            if (ch == 'c') {
                while ((ch = std::getc(f)) != EOF && ch != '\n') {}
            } else if (ch == 'p') {
                char fmt[16];
                if (std::fscanf(f, "%15s %d %d", fmt, &nvars, &nclauses) != 3) return false;
                break;
            }
        }
        clauses.reserve(nclauses);
        lits.reserve((size_t)nclauses * 3);
        std::vector<int> cur;
        cur.reserve(16);
        int x;
        while (std::fscanf(f, "%d", &x) == 1) {
            if (x == 0) {
                Clause c;
                c.start = (int)lits.size();
                c.size = (int)cur.size();
                c.w0 = 0;
                c.w1 = cur.size() > 1 ? 1 : 0;
                for (int lit : cur) lits.push_back(lit);
                clauses.push_back(c);
                cur.clear();
            } else {
                cur.push_back(x);
            }
        }
        std::fclose(f);
        bcp_val.assign(nvars + 1, 0);
        watch.assign((nvars + 1) * 2, {});
        for (int cid = 0; cid < (int)clauses.size(); ++cid) {
            Clause& c = clauses[cid];
            if (c.size == 0) return false;
            if (c.size == 1) {
                if (!assign_bcp(lits[c.start])) return false;
            } else {
                watch[lidx(lits[c.start + c.w0])].push_back(cid);
                watch[lidx(lits[c.start + c.w1])].push_back(cid);
            }
        }
        return true;
    }
    bool bcp() {
        while (!q.empty()) {
            int lit = q.front();
            q.pop_front();
            int false_idx = lidx(-lit);
            auto& ws = watch[false_idx];
            size_t out = 0;
            for (size_t p = 0; p < ws.size(); ++p) {
                int cid = ws[p];
                Clause& c = clauses[cid];
                int base = c.start;
                int wi_false, wi_other;
                if (lidx(lits[base + c.w0]) == false_idx) {
                    wi_false = c.w0;
                    wi_other = c.w1;
                } else {
                    wi_false = c.w1;
                    wi_other = c.w0;
                }
                int other = lits[base + wi_other];
                if (lit_val_partial(other) == 1) {
                    ws[out++] = cid;
                    continue;
                }
                bool moved = false;
                for (int i = 0; i < c.size; ++i) {
                    if (i == c.w0 || i == c.w1) continue;
                    int cand = lits[base + i];
                    if (lit_val_partial(cand) != -1) {
                        if (wi_false == c.w0) c.w0 = i; else c.w1 = i;
                        watch[lidx(cand)].push_back(cid);
                        moved = true;
                        break;
                    }
                }
                if (moved) continue;
                ws[out++] = cid;
                int ov = lit_val_partial(other);
                if (ov == -1) {
                    ws.resize(out);
                    return false;
                }
                if (ov == 0 && !assign_bcp(other)) {
                    ws.resize(out);
                    return false;
                }
            }
            ws.resize(out);
        }
        return true;
    }
    void build_occ() {
        std::vector<int> cnt(nvars + 1, 0);
        for (int lit : lits) ++cnt[std::abs(lit)];
        occ_start.assign(nvars + 2, 0);
        for (int v = 1; v <= nvars; ++v) occ_start[v + 1] = occ_start[v] + cnt[v];
        occs.resize(lits.size());
        std::vector<int> at = occ_start;
        for (int cid = 0; cid < (int)clauses.size(); ++cid) {
            const Clause& c = clauses[cid];
            for (int i = 0; i < c.size; ++i) {
                int lit = lits[c.start + i];
                int v = std::abs(lit);
                occs[at[v]++] = {cid, (signed char)(lit > 0 ? 1 : -1)};
            }
        }
    }
    void init_assignment(RNG& rng) {
        val.assign(nvars + 1, 1);
        fixed.assign(nvars + 1, 0);
        int fixed_count = 0;
        for (int v = 1; v <= nvars; ++v) {
            if (bcp_val[v]) {
                val[v] = bcp_val[v];
                fixed[v] = 1;
                ++fixed_count;
            } else {
                val[v] = (rng.next() & 1) ? 1 : -1;
            }
        }
        sat_count.assign(clauses.size(), 0);
        unsat.clear();
        unsat_pos.assign(clauses.size(), -1);
        for (int cid = 0; cid < (int)clauses.size(); ++cid) {
            const Clause& c = clauses[cid];
            int sc = 0;
            for (int i = 0; i < c.size; ++i) {
                if (lit_val_full(lits[c.start + i]) == 1) ++sc;
            }
            sat_count[cid] = (unsigned short)sc;
            if (sc == 0) add_unsat(cid);
        }
    }
    void add_unsat(int cid) {
        if (unsat_pos[cid] >= 0) return;
        unsat_pos[cid] = (int)unsat.size();
        unsat.push_back(cid);
    }
    void remove_unsat(int cid) {
        int p = unsat_pos[cid];
        if (p < 0) return;
        int last = unsat.back();
        unsat[p] = last;
        unsat_pos[last] = p;
        unsat.pop_back();
        unsat_pos[cid] = -1;
    }
    int break_count(int v) const {
        int br = 0;
        signed char oldv = val[v];
        for (int p = occ_start[v]; p < occ_start[v + 1]; ++p) {
            const Occ& o = occs[p];
            bool lit_true = (oldv == o.sign);
            if (lit_true && sat_count[o.cid] == 1) ++br;
        }
        return br;
    }
    int choose_var(int cid, RNG& rng) {
        const Clause& c = clauses[cid];
        int best_br = std::numeric_limits<int>::max();
        int choices[1024];
        int nchoices = 0;
        std::vector<int> big_choices;
        if (rng.uniform_int(100) < 4) {
            for (int i = 0; i < c.size; ++i) {
                int v = std::abs(lits[c.start + i]);
                if (!fixed[v]) {
                    if (c.size <= 1024) choices[nchoices++] = v;
                    else big_choices.push_back(v);
                }
            }
            if (nchoices) return choices[rng.uniform_int(nchoices)];
            if (!big_choices.empty()) return big_choices[rng.uniform_int((int)big_choices.size())];
        }
        for (int i = 0; i < c.size; ++i) {
            int v = std::abs(lits[c.start + i]);
            if (fixed[v]) continue;
            int br = break_count(v);
            if (br < best_br) {
                best_br = br;
                nchoices = 0;
                big_choices.clear();
            }
            if (br == best_br) {
                if (c.size <= 1024) choices[nchoices++] = v;
                else big_choices.push_back(v);
            }
        }
        if (nchoices) return choices[rng.uniform_int(nchoices)];
        if (!big_choices.empty()) return big_choices[rng.uniform_int((int)big_choices.size())];
        return 0;
    }
    void flip(int v) {
        signed char oldv = val[v];
        signed char newv = -oldv;
        val[v] = newv;
        for (int p = occ_start[v]; p < occ_start[v + 1]; ++p) {
            const Occ& o = occs[p];
            bool was_true = (oldv == o.sign);
            if (was_true) {
                unsigned short before = sat_count[o.cid]--;
                if (before == 1) add_unsat(o.cid);
            } else {
                unsigned short before = sat_count[o.cid]++;
                if (before == 0) remove_unsat(o.cid);
            }
        }
    }
    bool verify() const {
        for (const Clause& c : clauses) {
            bool sat = false;
            for (int i = 0; i < c.size; ++i) {
                if (lit_val_full(lits[c.start + i]) == 1) {
                    sat = true;
                    break;
                }
            }
            if (!sat) return false;
        }
        return true;
    }
};

int main(int argc, char** argv) {
    if (argc < 2 || argc > 3) {
        std::fprintf(stderr, "usage: sls formula.cnf [seconds]\n");
        return 2;
    }
    double limit = argc == 3 ? std::atof(argv[2]) : 60.0;
    Solver s;
    if (!s.read_dimacs(argv[1])) {
        std::cerr << "parse conflict\n";
        return 1;
    }
    if (!s.bcp()) {
        std::cerr << "BCP conflict\n";
        return 20;
    }
    int fixed_count = 0;
    for (int v = 1; v <= s.nvars; ++v) if (s.bcp_val[v]) ++fixed_count;
    std::cerr << "parsed vars=" << s.nvars << " clauses=" << s.clauses.size()
              << " lits=" << s.lits.size() << " fixed=" << fixed_count << "\n";
    s.build_occ();
    auto start = std::chrono::steady_clock::now();
    uint64_t seed = 88172645463325252ull;
    long long total_flips = 0;
    int restart = 0;
    while (true) {
        double elapsed = std::chrono::duration<double>(std::chrono::steady_clock::now() - start).count();
        if (elapsed >= limit) break;
        RNG rng(seed + 0x9e3779b97f4a7c15ull * (++restart));
        s.init_assignment(rng);
        std::cerr << "restart " << restart << " unsat=" << s.unsat.size() << " elapsed=" << elapsed << "\n";
        long long max_flips = 2000000LL + 500000LL * std::min(restart, 20);
        for (long long step = 0; step < max_flips; ++step) {
            if (s.unsat.empty()) {
                bool ok = s.verify();
                std::cerr << "SAT flips=" << total_flips + step << " verify=" << ok << "\n";
                if (!ok) return 1;
                std::cout << "s SATISFIABLE\nv ";
                int col = 0;
                for (int v = 1; v <= s.nvars; ++v) {
                    int lit = s.val[v] > 0 ? v : -v;
                    std::cout << lit << ' ';
                    if (++col == 20) {
                        std::cout << "\nv ";
                        col = 0;
                    }
                }
                std::cout << "0\n";
                return 10;
            }
            if ((step & 262143) == 0 && step) {
                double now = std::chrono::duration<double>(std::chrono::steady_clock::now() - start).count();
                std::cerr << "step " << (total_flips + step) << " unsat=" << s.unsat.size()
                          << " elapsed=" << now << "\n";
                if (now >= limit) break;
            }
            int cid = s.unsat[rng.uniform_int((int)s.unsat.size())];
            int v = s.choose_var(cid, rng);
            if (v == 0) {
                std::cerr << "unsat fixed clause " << cid << "\n";
                break;
            }
            s.flip(v);
        }
        total_flips += max_flips;
    }
    std::cerr << "UNKNOWN total_flips=" << total_flips << "\n";
    std::cout << "s UNKNOWN\n";
    return 0;
}
