| 1 | #define IDX(x) ((abs(x)-1)*2+((x)>0)) |
| 2 | struct SAT { |
| 3 | int n; |
| 4 | vi cl, head, tail, val; |
| 5 | vii log; vvi w, loc; |
| 6 | SAT() : n(0) { } |
| 7 | int var() { return ++n; } |
| 8 | void clause(vi vars) { |
| 9 | set<int> seen; iter(it,vars) { |
| 10 | if (seen.find(IDX(*it)^1) != seen.end()) return; |
| 11 | seen.insert(IDX(*it)); } |
| 12 | head.push_back(cl.size()); |
| 13 | iter(it,seen) cl.push_back(*it); |
| 14 | tail.push_back((int)cl.size() - 2); } |
| 15 | bool assume(int x) { |
| 16 | if (val[x^1]) return false; |
| 17 | if (val[x]) return true; |
| 18 | val[x] = true; log.push_back(ii(-1, x)); |
| 19 | rep(i,0,w[x^1].size()) { |
| 20 | int at = w[x^1][i], h = head[at], t = tail[at]; |
| 21 | log.push_back(ii(at, h)); |
| 22 | if (cl[t+1] != (x^1)) swap(cl[t], cl[t+1]); |
| 23 | while (h < t && val[cl[h]^1]) h++; |
| 24 | if ((head[at] = h) < t) { |
| 25 | w[cl[h]].push_back(w[x^1][i]); |
| 26 | swap(w[x^1][i--], w[x^1].back()); |
| 27 | w[x^1].pop_back(); |
| 28 | swap(cl[head[at]++], cl[t+1]); |
| 29 | } else if (!assume(cl[t])) return false; } |
| 30 | return true; } |
| 31 | bool bt() { |
| 32 | int v = log.size(), x; ll b = -1; |
| 33 | rep(i,0,n) if (val[2*i] == val[2*i+1]) { |
| 34 | ll s = 0, t = 0; |
| 35 | rep(j,0,2) { iter(it,loc[2*i+j]) |
| 36 | s+=1LL<<max(0,40-tail[*it]+head[*it]); swap(s,t); } |
| 37 | if (max(s,t) >= b) b = max(s,t), x = 2*i + (t>=s); } |
| 38 | if (b == -1 || (assume(x) && bt())) return true; |
| 39 | while (log.size() != v) { |
| 40 | int p = log.back().first, q = log.back().second; |
| 41 | if (p == -1) val[q] = false; else head[p] = q; |
| 42 | log.pop_back(); } |
| 43 | return assume(x^1) && bt(); } |
| 44 | bool solve() { |
| 45 | val.assign(2*n+1, false); |
| 46 | w.assign(2*n+1, vi()); loc.assign(2*n+1, vi()); |
| 47 | rep(i,0,head.size()) { |
| 48 | if (head[i] == tail[i]+2) return false; |
| 49 | rep(at,head[i],tail[i]+2) loc[cl[at]].push_back(i); } |
| 50 | rep(i,0,head.size()) if (head[i] < tail[i]+1) rep(t,0,2) |
| 51 | w[cl[tail[i]+t]].push_back(i); |
| 52 | rep(i,0,head.size()) if (head[i] == tail[i]+1) |
| 53 | if (!assume(cl[head[i]])) return false; |
| 54 | return bt(); } |
| 55 | bool get_value(int x) { return val[IDX(x)]; } }; |
| 56 | // vim: cc=60 ts=2 sts=2 sw=2: |
nothing calls this directly
no outgoing calls
no test coverage detected