#include<bits/stdc++.h>
#define ll long long
// NOTE:
// vertex-index must be 1-BASED
// Usage:
// SAT2 sat;
// sat.init(n);
// sat.addOR/addImply etc
// bool feasible = sat.computeSolution();
// result is sat.sol[1..n]. 0 is false, 1 is true.
struct SAT2
{
int n;
vector<int> *imply;
int *comp;
int *sol;
void init(int n_) {
n = n_;
imply = new vector<int>[n*2+1];
comp = new int[n*2+1];
sol = new int[n*2+1];
fill(sol, sol + n*2 + 1, -1);
}
int mask(int i) {
if (i >= 0) return i;
return (-i)+n;
}
void addImply(int u, int v) {
imply[mask(u)].push_back(mask(v));
}
void addOR(int u , int v) {
imply[mask(-u)].push_back(mask(v));
imply[mask(-v)].push_back(mask(u));
}
void addNAND(int u, int v) {
imply[mask(u)].push_back(mask(-v));
imply[mask(v)].push_back(mask(-u));
}
void addTRUE(int u) {
imply[mask(-u)].push_back(mask(u));
}
void addNOT(int u) {
addTRUE(-u);
}
void addXOR(int u, int v) {
addOR(u, v);
addNAND(u, v);
}
void addAND(int u, int v) {
addTRUE(u);
addTRUE(v);
}
void addNOR(int u, int v) {
addTRUE(-u);
addTRUE(-v);
}
void addXNOR(int u, int v) {
addXOR(u, -v);
}
bool computeSolution() {
// First, check if this problem has feasible solution
bool feasible = true;
Tarjan tarjan;
tarjan.init(n*2+1);
for (int u = 1; u <= n*2; ++u)
for (auto v : imply[u])
tarjan.addEdge(u, v);
vector<vector<int> > sccs = tarjan.findSCC();
fill(comp, comp + n*2+1, -1);
for (int i = 0; i < sccs.size(); ++i) {
for (int j = 0; j < sccs[i].size(); ++j)
comp[sccs[i][j]] = i+1;
}
for (int i = 1; i <= n; ++i)
if (comp[mask(i)] == comp[mask(-i)] && comp[mask(i)] > 0)
feasible = false;
if (!feasible)
return feasible;
// = End checking for feasible solution
// Find and return solution
for (int i = 1; i <= n; ++i) {
sol[mask(i)] = comp[mask(i)] < comp[mask(-i)];
sol[mask(-i)] = !sol[mask(i)];
}
return feasible;
// = End return solution
}
};