Little Artem and 2-SAT

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: . Note that there might be negations in 2-SAT formula (like for x 1 and for x 4).

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 nm 1 and m 2 (1 ≤ n ≤ 1000, 1 ≤ m 1, m 2 ≤ n 2) — the number of variables, the number of disjunctions in the first formula and the number of disjunctions in the second formula, respectively.

Next m 1 lines contains the description of 2-SAT formula f. The description consists of exactly m 1 pairs of integers x i ( - n ≤ x i ≤ n, x i ≠ 0) each on separate line, where x i > 0 corresponds to the variable without negation, while x i < 0 corresponds to the variable with negation. Each pair gives a single disjunction. Next m 2 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 x i () — 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 x 1 = 0 and x 2 = 0 we get the result 0, because . But the second formula is 1, because .

Solution:

#include<stdio.h>
#include<iostream>
#include<vector>
#include<bitset>
#include<cmath>
#include<algorithm>
#include<memory.h>
#include

<map>
#include<set>
#include<queue>
#include 	<list>
#include<sstream>
#include<cstring>
#define mp make_pair
#define pb push_back
#define F first
#define S second
#define SS stringstream
#define sqr(x) ((x)*(x))
#define m0(x) memset(x,0,sizeof(x))
#define m1(x) memset(x,63,sizeof(x))
#define CC(x) cout << (x) << endl
#define pw(x) (1ll<<(x))
#define buli(x) __builtin_popcountll(x)
#define forn(i, n) for(int i = 0 ; (i) < (n) ; ++i)
#define M 1000000007
#define N 2000222

#define TASK "1"

using namespace std;
typedef pair<int,int> pt;

unsigned int ed[2016][85];
unsigned int need[85];

int n, m[2];

int x[2][N], y[2][N];

int NOT(int x) {
return x < n ? x + n : x - n;
}

void ae(int a, int b) {
	ed[a][(b >> 5)] |= pw(b & 31);
//	ed[b][(a >> 5)] |= pw(a & 31);
}

int getv(int x) {
if (x > 0) return x - 1;
return -x - 1 + n;
}

int q[2016], q1, q2;

int d[2016][2016];

void findd() {
int sz = (n + n + 32) / 32;

for (int i = 0; i < n + n; i++) {
		for (int j = 0; j < sz; j++) need[j] = 0;

		for (int j = 0; j < n + n; j++) if (j != i) need[j >> 5] |= pw(j & 31);
q1 = q2 = 0;

q[q1++] = i;
while (q1 != q2) {
int x = q[q2++];
for (int i = 0; i < sz; i++) {
				unsigned int t = need[i] & ed[x][i];
				if (t != 0) for (int j = 0; j < 32; j++) if (t & pw(j)) {
					need[i] ^= pw(j);
					q[q1++] = i * 32 + j;
				}
			}
		}
		for (int j = 0; j < n + n; j++) if (need[j >> 5] & pw(j & 31)) d[i][j] = 0; else d[i][j] = 1;
}
}

vector<int> order;
int was[2016];

int ans[2016];

void go(int x) {
was[x] = 1;
for (int i = 0; i < n + n; i++) if (d[i][x] && !was[i]) go(i);
	order.pb(x);
}

void col(int x, int o) {
	if (was[x]) return;
	was[x] = o;
	for (int i = 0; i < n + n; i++) if (d[x][i]) col(i, o);

}

void solve(int A, int B) {
	for (int i = 0; i < n + n; i++) for (int j = 0; j < 80; j++) ed[i][j] = 0;

	for (int i = 0; i < m[A]; i++) {
		int a = getv(x[A][i]);
		int b = getv(y[A][i]);

		ae(NOT(a), b);
		ae(NOT(b), a);
	}
	findd();

/*	for (int i = 0; i < n + n; i++) {
		for (int j = 0; j < n + n; j++) cout << d[i][j];
		cout << endl;
	}*/
	int good = 1;
	for (int i = 0; i < n; i++) if (d[i][NOT(i)] && d[NOT(i)][i]) good = 0;
	if (!good) return;

	for (int i = 0; i < m[B]; i++) {
		int a = getv(x[B][i]);
		int b = getv(y[B][i]);

		//new a -> NOT(a)
//new b -> NOT(b)

int bad = 0;

if (d[NOT(a)][a] || d[NOT(b)][b]) bad = 1;

if (d[NOT(a)][b] && d[NOT(b)][a]) bad = 1;

if (d[NOT(b)][a] && d[NOT(a)][b]) bad = 1;

if (!bad) {
ae(a, NOT(a));
ae(b, NOT(b));

findd();
/*	for (int i = 0; i < n + n; i++) {
		for (int j = 0; j < n + n; j++) cout << d[i][j];
		cout << endl;
	}*/
			for (int i = 0; i < n + n; i++) was[i] = 0;
			order.clear();
			for (int i = 0; i < n + n; i++) if (!was[i]) go(i);

			int cc = 0;
			for (int i = 0; i < n + n; i++) was[i] = 0;
			for (int i = order.size() - 1; i >= 0; i--) {
int t = order[i];
if (was[t]) continue;
cc++;
col(t, cc);
}
/*			cout << "add " << a << " " << NOT(a) << endl;
			cout << "add " << b << " " << NOT(b) << endl;

			for (int i = 0; i < n + n; i++) cout << was[i] << " ";
			cout << endl;*/

			for (int i = 0; i < n; i++) {
				ans[i] = (was[i] < was[NOT(i)]);
				cout << ans[i];
				if (i + 1 == n) cout << endl; else cout << " ";
			}

			exit(0);
		}
	}

}

int main(){
	#ifdef home
		freopen(TASK".in","r",stdin);	
		freopen(TASK".out","w",stdout);
	#endif		
	cin >> n >> m[0] >> m[1];

for (int i = 0; i < 2; i++) for (int j = 0; j < m[i]; j++) scanf("%d%d", &x[i][j], &y[i][j]);

	solve(0, 1);
	solve(1, 0);

	puts("SIMILAR");

	return 0;
}