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>
#pragma GCC optimize("O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
using namespace std;
int a, b, c, d, n, m, k, m1, m2;
struct IG {
  bitset<1004> good[2004], bad[2004];
  bool bv[2004];
  IG() {
    for (int _n((2004) - 1), i(0); i <= _n; i++) {
      good[i].reset();
      bad[i].reset();
    }
    memset((bv), 0, sizeof(bv));
  }
  static inline int getNum(int a) {
    if (a > 0) return a - 1;
    a = -a;
    return n + a - 1;
  }
  static inline int neg(int a) {
    if (a < n)
      return a + n;
    else
      return a - n;
  }
  inline void addImplication(int a, int b) {
    a = getNum(a);
    b = getNum(b);
    if (b < n) {
      good[a].set(b);
    } else {
      bad[a].set(b - n);
    }
  }
  inline void add(int a, int b) {
    addImplication(-a, b);
    addImplication(-b, a);
  }
  void transitiveClosure() {
    for (int _n((2 * n) - 1), i(0); i <= _n; i++) {
      if (i < n) {
        good[i].set(i);
      } else {
        bad[i].set(i - n);
      }
    }
    for (int _n((2 * n) - 1), mid(0); mid <= _n; mid++) {
      for (int _n((2 * n) - 1), i(0); i <= _n; i++) {
        bool ok = 0;
        if (mid < n) {
          if (good[i].test(mid)) {
            ok = 1;
          }
        } else {
          if (bad[i].test(mid - n)) {
            ok = 1;
          }
        }
        if (ok) {
          good[i] |= good[mid];
          bad[i] |= bad[mid];
        }
      }
    }
    for (int _n((2 * n) - 1), i(0); i <= _n; i++) {
      if (i < n) {
        if (bad[i].test(i)) bv[i] = 1;
      } else {
        if (good[i].test(i - n)) bv[i] = 1;
      }
    }
    for (int _n((2 * n) - 1), i(0); i <= _n; i++) {
      for (int _n((2 * n) - 1), j(0); j <= _n; j++) {
        if (!bv[j]) continue;
        if (j < n) {
          if (good[i].test(j)) bv[i] = 1;
        } else {
          if (bad[i].test(j - n)) bv[i] = 1;
        }
      }
    }
  }
  bool hasSolution() {
    for (int _n((n)-1), i(0); i <= _n; i++) {
      if (bad[i].test(i) && good[i + n].test(i)) {
        return 0;
      }
    }
    return 1;
  }
  int num[1004], sof[1004];
  inline bool select(int v) {
    int t = v;
    if (num[v] == 0) t += n;
    if (bv[t]) return false;
    int k = 0;
    sof[k++] = v;
    bool ok = 1;
    for (int _n((n)-1), i(0); i <= _n; i++) {
      if (good[t].test(i)) {
        if (num[i] == 0) {
          ok = 0;
          break;
        }
        if (num[i] == -1) {
          num[i] = 1;
          sof[k++] = i;
        }
      }
      if (bad[t].test(i)) {
        if (num[i] == 1) {
          ok = 0;
          break;
        }
        if (num[i] == -1) {
          num[i] = 0;
          sof[k++] = i;
        }
      }
    }
    if (!ok) {
      for (int _n((k)-1), i(0); i <= _n; i++) {
        num[sof[i]] = -1;
      }
      return 0;
    }
    return 1;
  }
  void printSolutionAndDie(int f1, int f2) {
    memset(num, -1, sizeof(num));
    if (f1 != -1) {
      if (f1 < n) {
        num[f1] = 1;
      } else {
        f1 -= n;
        num[f1] = 0;
      }
      select(f1);
    }
    if (f2 != -1) {
      if (num[f2 < n ? f2 : f2 - n] == -1) {
        if (f2 < n) {
          num[f2] = 1;
        } else {
          f2 -= n;
          num[f2] = 0;
        }
        select(f2);
      }
    }
    for (int _n((n)-1), i(0); i <= _n; i++) {
      if (num[i] != -1) continue;
      num[i] = 0;
      if (!select(i)) {
        num[i] = 1;
        select(i);
      }
    }
    for (int _n((n)-1), i(0); i <= _n; i++) {
      if (i) printf(" ");
      printf("%d", num[i]);
    }
    printf("\n");
    exit(0);
  }
  inline bool checkBad(int v1, int v2) {
    auto t = (good[v1] | good[v2]) & (bad[v1] | bad[v2]);
    if (t.any()) {
      return 1;
    } else {
      return 0;
    }
  }
};
char buf[65537];
char *ch = buf;
inline char get_char() {
  if (*ch == 0) {
    ch = buf;
    fread(buf, sizeof(char), 65536, stdin);
  }
  return *(ch++);
}
char _ch;
inline void next_int(int &ans) {
  ans = 0;
  while (((_ch = get_char()) < '0' || _ch > '9') && _ch != '-')
    ;
  bool neg = 0;
  if (_ch == '-') {
    neg = 1;
    _ch = get_char();
  }
  do {
    ans = ans * 10 + _ch - '0';
  } while ((_ch = get_char()) >= '0' && _ch <= '9');
  if (neg) ans = -ans;
}
IG g1, g2;
bool used[2002][2002];
pair<int, int> cl1[1000002], cl2[1000002];
inline void solve(pair<int, int> *cl1, pair<int, int> *cl2, IG &g1, IG &g2,
                  int m1, int m2) {
  memset((used), 0, sizeof(used));
  for (int _n((m1)-1), i(0); i <= _n; i++) {
    int v1 = IG::getNum(cl1[i].first);
    int v2 = IG::getNum(cl1[i].second);
    v1 = IG::neg(v1);
    v2 = IG::neg(v2);
    if (v1 > v2) swap(v1, v2);
    if (used[v1][v2]) continue;
    used[v1][v2] = 1;
    if (g2.bv[v1] || g2.bv[v2]) continue;
    if (g2.checkBad(v1, v2)) continue;
    g2.printSolutionAndDie(v1, v2);
  }
}
int main() {
  next_int(n);
  next_int(m1);
  next_int(m2);
  for (int _n((m1)-1), i(0); i <= _n; i++) {
    next_int(a);
    next_int(b);
    cl1[i] = make_pair(a, b);
    g1.add(a, b);
  }
  for (int _n((m2)-1), i(0); i <= _n; i++) {
    next_int(a);
    next_int(b);
    cl2[i] = make_pair(a, b);
    g2.add(a, b);
  }
  g1.transitiveClosure();
  g2.transitiveClosure();
  bool r1 = g1.hasSolution();
  bool r2 = g2.hasSolution();
  if (!r1 && !r2) {
    printf("SIMILAR\n");
    exit(0);
  }
  if (!r1) {
    g2.printSolutionAndDie(-1, -1);
  }
  if (!r2) {
    g1.printSolutionAndDie(-1, -1);
  }
  solve(cl1, cl2, g1, g2, m1, m2);
  solve(cl2, cl1, g2, g1, m2, m1);
  printf("SIMILAR\n");
}
