#include <fstream>
#include <vector>
#include <algorithm>
#include <random>
#include <unordered_map>
#include <set>
#include <queue>
#include <bitset>
#include <stack>
#define ll long long
#define nl '\n'
#define FOR(i, a, b) for (int i = a; i <= b; ++i)
#define F0R(i, a, b) for (int i = a; i >= b; --i)
#define FORd(i, n) for (int i = 0; i < n; ++i)
#define F0Rd(i, n) for (int i = n - 1; i >= 0; --i)
#define trav(a, x) for (auto &a : x)
#define uid(a, b) uniform_int_distribution<int>(a, b)(rng)
int not_x(int x, int n) {
if (x <= n) {
return n + x;
}
return x - n;
}
const int mxN = 2e5 + 10;
int timestamp, curr_component;
std::bitset<mxN> in_stack;
std::bitset<mxN> visited;
std::stack<int> visiting;
int found[mxN], low_link[mxN];
void dfs(int node, std::vector<int> graph[], std::vector<int> components[], std::unordered_map<int, int> &components_mapping) {
found[node] = low_link[node] = ++timestamp;
visiting.push(node);
in_stack[node] = 1;
visited[node] = 1;
for (int x : graph[node]) {
if (!visited[x]) {
dfs(x, graph, components, components_mapping);
low_link[node] = std::min(low_link[node], low_link[x]);
} else if (in_stack[x]) {
low_link[node] = std::min(low_link[node], found[x]);
}
}
if (found[node] == low_link[node]) {
while (true) {
int x = visiting.top();
visiting.pop();
in_stack[x] = 0;
components[curr_component].push_back(x);
components_mapping[x] = curr_component;
if (x == node) break;
}
curr_component++;
}
}
void build_components(std::vector<int> graph[], std::vector<int> components[], std::unordered_map<int, int> &components_mapping, int nodes) {
/* Use tarjan algorithm. */
for (int i = 1; i < nodes; ++i) {
if (!visited[i]) {
dfs(i, graph, components, components_mapping);
}
}
}
std::vector<int> topological_sort(std::vector<int> graph[], int nodes) {
/* Use kahn algorithm. */
std::vector<int> order;
std::vector<int> in_degree(nodes, 0);
std::queue<int> q;
for (int i = 1; i < nodes; ++i) {
for (int x : graph[i]) {
in_degree[x]++;
}
}
for (int i = 1; i < nodes; ++i) {
if (in_degree[i] == 0) {
q.push(i);
}
}
while (!q.empty()) {
int node = q.front();
q.pop();
order.push_back(node);
for (int x : graph[node]) {
in_degree[x]--;
if (in_degree[x] == 0) {
q.push(x);
}
}
}
return order;
}
int main() {
int n, m;
std::ifstream fin("2sat.in");
std::ofstream fout("2sat.out");
fin >> n >> m;
std::vector<int> edges[2 * n + 1];
std::vector<std::pair<int, int>> all_edges;
while (m--) {
int x, y;
fin >> x >> y;
if (x < 0) x = n - x;
if (y < 0) y = n - y;
edges[not_x(x, n)].push_back(y);
edges[not_x(y, n)].push_back(x);
all_edges.push_back({not_x(x, n), y});
all_edges.push_back({not_x(y, n), x});
}
std::unordered_map<int, int> components_mapping;
std::vector<int> components[2 * n + 1];
build_components(edges, components, components_mapping, 2 * n + 1);
/* Check if formula is satisfiable. */
for (int i = 1; i < n; ++i) {
if (components_mapping[i] == components_mapping[i + n]) {
fout << -1 << nl;
return 0;
}
}
std::vector<int> compressed_graph[2 * n + 1];
std::set<std::pair<int, int>> used_compressed_edges;
for (auto &[x, y] : all_edges) {
int cx = components_mapping[x], cy = components_mapping[y];
if (cx == cy) continue;
if (used_compressed_edges.find({cx, cy}) != used_compressed_edges.end()) continue;
compressed_graph[cx].push_back(cy);
used_compressed_edges.insert({cx, cy});
}
std::vector<int> order = topological_sort(compressed_graph, 2 * n + 1);
std::reverse(order.begin(), order.end());
std::vector<int> result(2 * n + 1, -1);
for (int i = 0; i < order.size(); ++i) {
int component = order[i];
for (int x : components[component]) {
if (result[x] == -1) {
result[x] = 1;
result[not_x(x, n)] = 0;
}
}
}
for (int i = 1; i <= n; ++i) {
fout << result[i] << " ";
}
return 0;
}