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 rand(); }
inline int rnd(int x) { return myrand() % x; }
const int inf = (int)1.01e9;
const long double eps = 1e-9;
const long double pi = acos(-1.0L);
void precalc() {}
const int maxn = 2 * 1000 + 10;
int n, m[2];
int a[2][maxn * maxn][2];
bool read() {
  if (scanf("%d%d%d", &n, &m[0], &m[1]) < 3) {
    return 0;
  }
  for (int it = 0; it < 2; ++it) {
    for (int i = 0; i < m[it]; ++i) {
      for (int j = 0; j < 2; ++j) {
        int x;
        scanf("%d", &x);
        a[it][i][j] = 2 * (abs(x) - 1) + (x < 0);
      }
    }
  }
  return 1;
}
vector<vector<int> > es, esrev;
const int maxv = 2 * maxn;
int used[maxv];
int tme;
int perm[maxv];
void dfs1(int v) {
  used[v] = 1;
  for (int it = 0; it < ((int)(es[v]).size()); ++it) {
    int u = es[v][it];
    if (used[u]) {
      continue;
    }
    dfs1(u);
  }
  perm[tme++] = v;
}
int col[maxv];
int maxc;
void dfs2(int v) {
  col[v] = maxc;
  for (int it = 0; it < ((int)(esrev[v]).size()); ++it) {
    int u = esrev[v][it];
    if (col[u] != -1) {
      continue;
    }
    dfs2(u);
  }
}
bool buildTopSort() {
  int cnt = 2 * n;
  for (int i = 0; i < cnt; ++i) {
    used[i] = 0;
  }
  tme = 0;
  for (int i = 0; i < cnt; ++i) {
    if (used[i]) {
      continue;
    }
    dfs1(i);
  }
  assert(tme == cnt);
  esrev = vector<vector<int> >(cnt);
  for (int i = 0; i < cnt; ++i) {
    for (int it = 0; it < ((int)(es[i]).size()); ++it) {
      esrev[es[i][it]].push_back(i);
    }
  }
  for (int i = 0; i < cnt; ++i) {
    col[i] = -1;
  }
  maxc = 0;
  for (int i = 0; i < cnt; ++i) {
    int v = perm[cnt - 1 - i];
    if (col[v] != -1) {
      continue;
    }
    dfs2(v);
    ++maxc;
  }
  bool fail = 0;
  for (int i = 0; i < n; ++i) {
    if (col[2 * i] == col[2 * i + 1]) {
      return 0;
    }
  }
  return 1;
}
struct Set {
  const static int k = maxv / 32 + 3;
  unsigned a[k];
  Set() { memset(a, 0, sizeof(a)); }
  int get(int x) { return ((a[x >> 5] >> (x & 31)) & 1); }
  inline void operator|=(const Set &s) {
    for (int i = 0; i < k; ++i) {
      a[i] |= s.a[i];
    }
  }
};
Set go[maxv];
int ans[maxn];
void solve() {
  for (int ist = 0; ist < 2; ++ist) {
    int cnt = 2 * n;
    es = vector<vector<int> >(cnt);
    for (int i = 0; i < m[ist]; ++i) {
      es[1 ^ a[ist][i][0]].push_back(a[ist][i][1]);
      es[1 ^ a[ist][i][1]].push_back(a[ist][i][0]);
    }
    if (!buildTopSort()) {
      continue;
    }
    for (int i = 0; i < maxc; ++i) {
      go[i] = Set();
    }
    for (int i = cnt - 1; i >= 0; --i) {
      int v = perm[cnt - 1 - i];
      Set &cur = go[col[v]];
      cur.a[v >> 5] |= (1u << (v & 31));
      for (int it = 0; it < ((int)(es[v]).size()); ++it) {
        int u = es[v][it];
        cur |= go[col[u]];
      }
    }
    for (int j1 = 0; j1 < m[!ist]; ++j1) {
      int s = a[!ist][j1][0];
      int t = a[!ist][j1][1];
      s ^= 1, t ^= 1;
      if (go[col[s]].get(s ^ 1) || go[col[s]].get(t ^ 1) ||
          go[col[t]].get(s ^ 1) || go[col[t]].get(t ^ 1)) {
        continue;
      }
      es[s ^ 1].push_back(s);
      es[t ^ 1].push_back(t);
      assert(buildTopSort());
      for (int i = 0; i < n; ++i) {
        ans[i] = (col[2 * i] > col[2 * i + 1]);
        printf("%d%c", ans[i], " \n"[i == n - 1]);
      }
      return;
    }
  }
  printf("SIMILAR\n");
}
int main() {
  srand(rdtsc());
  precalc();
  while (1) {
    if (!read()) {
      break;
    }
    solve();
  }
  return 0;
}
