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;
const long double pi = acos(-1.0);
const long double eps = 1e-9;
const int INF = 1E9;
const int MAXN = 2050;
int makeId(int a) {
  int odd = (a > 0 ? 0 : 1);
  a = (abs(a) - 1) * 2 + odd;
  return a;
}
int n, m[2];
vector<int> g[2][MAXN], ig[2][MAXN];
int compNum[2], compId[2][MAXN], used[2][MAXN];
vector<int> comps[2][MAXN];
bitset<MAXN> canReach[2][MAXN];
int fxd[2][MAXN], val[2][MAXN];
int sz;
int order[MAXN];
bool solvable[2];
int a, b;
void dfs1(int id, int v) {
  used[id][v] = 1;
  for (auto w : g[id][v])
    if (!used[id][w]) dfs1(id, w);
  order[sz++] = v;
}
void dfs2(int id, int v) {
  comps[id][compNum[id]].push_back(v);
  compId[id][v] = compNum[id];
  used[id][v] = 1;
  for (auto w : ig[id][v])
    if (!used[id][w]) dfs2(id, w);
}
void solve2sat(int id) {
  memset(used[id], 0, sizeof(used[id]));
  sz = 0;
  for (int i = 0; i < (int)(2 * n); i++)
    if (!used[id][i]) dfs1(id, i);
  reverse(order, order + 2 * n);
  memset(used[id], 0, sizeof(used[id]));
  compNum[id] = 0;
  for (int i = 0; i < (int)(2 * n); i++) {
    int v = order[i];
    if (!used[id][v]) {
      dfs2(id, v);
      compNum[id]++;
    }
  }
  for (int k = 0; k < (int)(2 * n); k++)
    for (int i = 0; i < (int)(2 * n); i++)
      if (canReach[id][i][k]) canReach[id][i] |= canReach[id][k];
  for (int i = 0; i < (int)(n); i++)
    if (compId[id][2 * i] == compId[id][2 * i + 1]) {
      solvable[id] = 0;
      return;
    }
  solvable[id] = 1;
  memset(fxd[id], 0, sizeof(fxd[id]));
  for (int i = 0; i < (int)(n); i++) {
    assert(!canReach[id][2 * i + 1][2 * i] || !canReach[id][2 * i][2 * i + 1]);
    if (canReach[id][2 * i + 1][2 * i]) {
      fxd[id][i] = 1;
      val[id][i] = 1;
    } else if (canReach[id][2 * i][2 * i + 1]) {
      fxd[id][i] = 1;
      val[id][i] = 0;
    }
  }
}
void dfs3(int id, int v) {
  for (auto w : g[id][v]) {
    int z = (w >> 1);
    if (!fxd[id][z]) {
      fxd[id][z] = 1;
      val[id][z] = (w & 1) ^ 1;
      dfs3(id, (2 * z) ^ val[id][z] ^ 1);
    }
  }
}
void fixVariables(int id) {
  for (int i = 0; i < (int)(n); i++)
    if (fxd[id][i]) dfs3(id, (2 * i) ^ val[id][i] ^ 1);
}
pair<int, int> queries[2][MAXN * MAXN];
int result[2];
void genAnswer(int id) {
  for (int i = 0; i < (int)(n); i++)
    if (!fxd[id][i]) {
      fxd[id][i] = 1;
      if (compId[id][2 * i] < compId[id][2 * i + 1]) {
        val[id][i] = 0;
      } else {
        val[id][i] = 1;
      }
    }
  for (int t = 0; t < (int)(2); t++) {
    result[t] = 1;
    for (int i = 0; i < (int)(m[t]); i++) {
      int v1 = abs(queries[t][i].first) - 1;
      int v2 = abs(queries[t][i].second) - 1;
      int z1 = (queries[t][i].first > 0 ? 0 : 1);
      int z2 = (queries[t][i].second > 0 ? 0 : 1);
      result[t] &= ((val[id][v1] ^ z1) || (val[id][v2] ^ z2));
    }
  }
  for (int i = 0; i < (int)(n); i++) {
    printf("%d%c", val[id][i], " \n"[i == n - 1]);
  }
}
void addEdge(int id, int a, int b) {
  canReach[id][a ^ 1][b] = 1;
  canReach[id][b ^ 1][a] = 1;
  g[id][a ^ 1].push_back(b);
  ig[id][b].push_back(a ^ 1);
  g[id][b ^ 1].push_back(a);
  ig[id][a].push_back(b ^ 1);
}
int main() {
  scanf("%d%d%d", &n, &m[0], &m[1]);
  for (int id = 0; id < (int)(2); id++) {
    for (int j = 0; j < (int)(2 * n); j++) canReach[id][j][j] = 1;
    for (int j = 0; j < (int)(m[id]); j++) {
      scanf("%d%d", &a, &b);
      queries[id][j] = {a, b};
      a = makeId(a);
      b = makeId(b);
      addEdge(id, a, b);
    }
    solve2sat(id);
  }
  if (!solvable[0] && !solvable[1]) {
    cout << "SIMILAR\n";
  } else if (solvable[0] != solvable[1]) {
    for (int i = 0; i < (int)(2); i++)
      if (solvable[i]) {
        genAnswer(i);
        return 0;
      }
  } else {
    for (int id = 0; id < (int)(2); id++) fixVariables(id);
    for (int i = 0; i < (int)(n); i++) {
      if ((fxd[0][i] != fxd[1][i]) ||
          (fxd[0][i] && fxd[1][i] && val[0][i] != val[1][i])) {
        int id = 0;
        if (fxd[id][i]) id ^= 1;
        if (!fxd[id][i]) {
          fxd[id][i] = 1;
          val[id][i] = !val[id ^ 1][i];
          dfs3(id, (2 * i) ^ val[id][i] ^ 1);
        }
        genAnswer(id);
        return 0;
      }
    }
    for (int i = 0; i < (int)(2 * n); i++)
      for (int j = 0; j < (int)(2 * n); j++) {
        bool ok = 1;
        for (int id = 0; id < (int)(2); id++) {
          if (fxd[id][i >> 1]) ok = 0;
          if (fxd[id][j >> 1]) ok = 0;
        }
        if (!ok) continue;
        if ((i >> 1) != (j >> 1) && canReach[0][i][j] != canReach[1][i][j]) {
          for (int id = 0; id < (int)(2); id++)
            if (canReach[id][i][j]) {
              int qi = (i >> 1);
              int qj = (j >> 1);
              fxd[id ^ 1][qi] = 1;
              fxd[id ^ 1][qj] = 1;
              val[id ^ 1][qi] = (i & 1) ^ 1;
              val[id ^ 1][qj] = (j & 1);
              dfs3(id ^ 1, (2 * qi) ^ val[id ^ 1][qi] ^ 1);
              dfs3(id ^ 1, (2 * qj) ^ val[id ^ 1][qj] ^ 1);
              genAnswer(id ^ 1);
              return 0;
            }
        }
      }
    cout << "SIMILAR\n";
  }
  return 0;
}
