#include <fstream>
#include <stack>
#include <vector>
using namespace std;
struct Node
{
vector<int> edges;
int low = -1;
int time = -1;
int comp = -1;
bool in_stack = false;
};
struct Graph
{
vector<Node> nodes;
int terms;
Graph(int terms) : nodes(2 * terms + 3), terms(terms) {}
void AddClause(int logical1, int logical2);
int GetIndex(int logical) const;
int GetLogical(int index) const;
};
void Graph::AddClause(int logical1, int logical2)
{
int index1 = GetIndex(logical1);
int index2 = GetIndex(logical2);
int index_not1 = GetIndex(-logical1);
int index_not2 = GetIndex(-logical2);
nodes[index_not1].edges.push_back(index2);
nodes[index_not2].edges.push_back(index1);
}
int Graph::GetIndex(int logical) const
{
if (logical > 0) {
return logical;
}
return terms - logical;
}
int Graph::GetLogical(int index) const
{
if (index <= terms) {
return index;
}
return terms - index;
}
void ExtractComponent(Graph &g, int last_node, stack<int> &st, vector<int> &order)
{
static int curr_comp = 0;
curr_comp += 1;
while (order.empty() || order.back() != last_node) {
g.nodes[st.top()].comp = curr_comp;
g.nodes[st.top()].in_stack = false;
order.push_back(st.top());
st.pop();
}
}
void Tarjan(Graph &g, int node, stack<int> &st, vector<int> &order)
{
static int time = 0;
g.nodes[node].low = g.nodes[node].time = (time += 1);
st.push(node);
g.nodes[node].in_stack = true;
for (const auto &next : g.nodes[node].edges) {
if (g.nodes[next].time == -1) {
Tarjan(g, next, st, order);
g.nodes[node].low = min(g.nodes[node].low, g.nodes[next].low);
}
if (g.nodes[next].in_stack) {
g.nodes[node].low = min(g.nodes[node].low, g.nodes[next].time);
}
}
if (g.nodes[node].low >= g.nodes[node].time) {
ExtractComponent(g, node, st, order);
}
}
vector<int> FindOrder(Graph &g)
{
vector<int> order;
for (int i = 1; i <= 2 * g.terms; i += 1) {
if (g.nodes[i].time == -1) {
stack<int> st;
Tarjan(g, i, st, order);
}
}
return order;
}
vector<bool> TwoSat(Graph &g)
{
auto order = FindOrder(g);
vector<bool> res(g.terms, false);
vector<bool> set(g.terms, false);
for (int i = order.size() - 1; i >= 0; i -= 1) {
auto index = order[i];
auto index_not = g.GetIndex(-g.GetLogical(index));
if (g.nodes[index].comp == g.nodes[index_not].comp) {
return vector<bool>();
}
auto value = (g.GetLogical(index) > 0 ? false : true);
auto res_index = abs(g.GetLogical(index)) - 1;
if (!set[res_index]) {
res[res_index] = value;
set[res_index] = true;
}
}
return res;
}
int main()
{
ifstream fin("2sat.in");
ofstream fout("2sat.out");
int terms, clauses;
fin >> terms >> clauses;
Graph graph(terms);
for (int i = 0; i < clauses; i += 1) {
int a, b;
fin >> a >> b;
graph.AddClause(a, b);
}
auto res = TwoSat(graph);
if (res.empty()) {
fout << "-1\n";
return 0;
}
for (const auto &b : res) {
fout << (b ? 1 : 0) << " ";
}
fout << "\n";
return 0;
}