Little Artem is a very smart programmer. He knows many different difficult algorithms. Recently he has mastered in 2-SAT one.

In computer science, 2-satisfiability (abbreviated as 2-SAT) is the special case of the problem of determining whether a conjunction (logical AND) of disjunctions (logical OR) have a solution, in which all disjunctions consist of no more than two arguments (variables). For the purpose of this problem we consider only 2-SAT formulas where each disjunction consists of exactly two arguments.

Consider the following 2-SAT problem as an example: <image>. Note that there might be negations in 2-SAT formula (like for x1 and for x4).

Artem now tries to solve as many problems with 2-SAT as possible. He found a very interesting one, which he can not solve yet. Of course, he asks you to help him. 

The problem is: given two 2-SAT formulas f and g, determine whether their sets of possible solutions are the same. Otherwise, find any variables assignment x such that f(x) ≠ g(x). 

Input

The first line of the input contains three integers n, m1 and m2 (1 ≤ n ≤ 1000, 1 ≤ m1, m2 ≤ n2) — the number of variables, the number of disjunctions in the first formula and the number of disjunctions in the second formula, respectively.

Next m1 lines contains the description of 2-SAT formula f. The description consists of exactly m1 pairs of integers xi ( - n ≤ xi ≤ n, xi ≠ 0) each on separate line, where xi > 0 corresponds to the variable without negation, while xi < 0 corresponds to the variable with negation. Each pair gives a single disjunction. Next m2 lines contains formula g in the similar format.

Output

If both formulas share the same set of solutions, output a single word "SIMILAR" (without quotes). Otherwise output exactly n integers xi (<image>) — any set of values x such that f(x) ≠ g(x).

Examples

Input

2 1 1
1 2
1 2


Output

SIMILAR


Input

2 1 1
1 2
1 -2


Output

0 0 

Note

First sample has two equal formulas, so they are similar by definition.

In second sample if we compute first function with x1 = 0 and x2 = 0 we get the result 0, because <image>. But the second formula is 1, because <image>.
#include <bits/stdc++.h>
using namespace std;
long long rdtsc() {
  long long tmp;
  asm("rdtsc" : "=A"(tmp));
  return tmp;
}
inline int myrand() { return abs((rand() << 15) ^ rand()); }
inline int rnd(int x) { return myrand() % x; }
void precalc() {}
const int maxn = 2e3 + 10;
int n;
vector<vector<int> > to[2];
vector<vector<int> > inv[2];
bool read() {
  int m[2];
  if (scanf("%d%d%d", &n, &m[0], &m[1]) < 3) {
    return false;
  }
  for (int it = 0; it < 2; ++it) {
    to[it] = vector<vector<int> >(2 * n);
    inv[it] = vector<vector<int> >(2 * n);
    for (int i = 0; i < m[it]; ++i) {
      int x, y;
      scanf("%d%d", &x, &y);
      if (x < 0) {
        x = -x;
      } else {
        x += n;
      }
      if (y < 0) {
        y = -y;
      } else {
        y += n;
      }
      --x, --y;
      x = (x + n) % (2 * n);
      for (int q = 0; q < 2; ++q) {
        to[it][x].push_back(y);
        inv[it][y].push_back(x);
        x = (x + n) % (2 * n);
        y = (y + n) % (2 * n);
        swap(x, y);
      }
    }
  }
  return true;
}
bool used[maxn];
int clr[2][maxn];
vector<vector<int> > cto[2];
int cnt[2];
vector<int> top;
void topsort(int v, int it) {
  used[v] = true;
  for (auto u : to[it][v]) {
    if (!used[u]) {
      topsort(u, it);
    }
  }
  top.push_back(v);
}
void condense(int v, int it) {
  used[v] = true;
  for (auto u : inv[it][v]) {
    if (used[u]) {
      continue;
    }
    clr[it][u] = clr[it][v];
    condense(u, it);
  }
}
bitset<maxn> b[2][maxn];
bool cool[2];
int ans[maxn];
void solve(int it, const vector<int>& st) {
  bitset<maxn> tmp;
  tmp.reset();
  for (auto v : st) {
    tmp[v] = 1;
  }
  for (int v = 0; v < n; ++v) {
    bool fnd = false;
    for (int q = 0; q < 2; ++q) {
      bitset<maxn> tmp2 = tmp | b[it][clr[it][v + q * n]];
      if ((tmp2 & (tmp2 >> n)).count()) {
        continue;
      }
      fnd = true;
      tmp = tmp2;
      ans[v] = q;
      break;
    }
    assert(fnd);
  }
  for (int i = 0; i < n; ++i) {
    printf("%d%c", ans[i], " \n"[i == n - 1]);
  }
}
void solve() {
  for (int it = 0; it < 2; ++it) {
    memset(used, 0, sizeof(used[0]) * (2 * n));
    top.clear();
    for (int i = 0; i < 2 * n; ++i) {
      if (!used[i]) {
        topsort(i, it);
      }
    }
    assert(((int)(top).size()) == 2 * n);
    reverse(top.begin(), top.end());
    cnt[it] = 0;
    memset(used, 0, sizeof(used[0]) * (2 * n));
    for (auto v : top) {
      if (used[v]) {
        continue;
      }
      clr[it][v] = cnt[it]++;
      condense(v, it);
    }
    cto[it] = vector<vector<int> >(cnt[it]);
    for (int v = 0; v < 2 * n; ++v) {
      for (auto u : to[it][v]) {
        if (clr[it][v] == clr[it][u]) {
          continue;
        }
        cto[it][clr[it][v]].push_back(clr[it][u]);
      }
    }
    for (int v = 0; v < cnt[it]; ++v) {
      b[it][v].reset();
    }
    for (int v = 0; v < 2 * n; ++v) {
      b[it][clr[it][v]][v] = 1;
    }
    for (int v = cnt[it] - 1; v >= 0; --v) {
      for (auto u : cto[it][v]) {
        b[it][v] |= b[it][u];
      }
    }
    cool[it] = true;
    for (int v = 0; v < n; ++v) {
      int c1 = clr[it][v], c2 = clr[it][n + v];
      if (c1 == c2) {
        cool[it] = false;
        break;
      }
    }
  }
  if (!cool[0] && !cool[1]) {
    printf("SIMILAR\n");
    return;
  }
  if (!cool[0] || !cool[1]) {
    solve(cool[0] ? 0 : cool[1], vector<int>());
    return;
  }
  for (int it = 0; it < 2; ++it) {
    for (int v = 0; v < 2 * n; ++v) {
      for (auto u : to[it][v]) {
        int x = v, y = (u + n) % (2 * n);
        bitset<maxn> tmp = b[!it][clr[!it][x]] | b[!it][clr[!it][y]];
        if (!((tmp >> n) & tmp).count()) {
          solve(!it, {x, y});
          return;
        }
      }
    }
  }
  printf("SIMILAR\n");
}
int main() {
  srand(rdtsc());
  precalc();
  while (true) {
    if (!read()) {
      break;
    }
    solve();
  }
  return 0;
}
