Problem: Welcome to the world of Pokermon, yellow little mouse-like creatures, who absolutely love playing poker! 

Yeah, right… 

In the ensuing Pokermon League, there are n registered Pokermon trainers, and t existing trainer teams each of which belongs to one of two conferences. Since there is a lot of jealousy between trainers, there are e pairs of trainers who hate each other. Their hate is mutual, there are no identical pairs among these, and no trainer hates himself (the world of Pokermon is a joyful place!). Each trainer has a wish-list of length li of teams he’d like to join.

Your task is to divide players into teams and the teams into two conferences, so that: 

  * each trainer belongs to exactly one team; 
  * no team is in both conferences; 
  * total hate between conferences is at least e / 2; 
  * every trainer is in a team from his wish-list. 



Total hate between conferences is calculated as the number of pairs of trainers from teams from different conferences who hate each other. 

Input

The first line of the input contains two integer n (4 ≤ n ≤ 50 000) and e (2 ≤ e ≤ 100 000) — the total number of Pokermon trainers and the number of pairs of trainers who hate each other.

Pokermon trainers are numbered from 1 to n. Next e lines contain two integers a and b (1 ≤ a, b ≤ n) indicating that Pokermon trainers a and b hate each other. Next 2n lines are in a following format. Starting with Pokermon trainer 1, for each trainer in consecutive order: first number li (16 ≤ li ≤ 20) — a size of Pokermon trainers wish list, then li positive integers ti, j (1 ≤ ti, j ≤ T), providing the teams the i-th trainer would like to be on.

Each trainers wish list will contain each team no more than once. Teams on the wish lists are numbered in such a way that the set of all teams that appear on at least 1 wish list is set of consecutive positive integers {1, 2, 3, …, T}. Here T might be up to 1 000 000.

Output

Print two lines. The first line should contain n numbers, specifying for each trainer the team he is in.

The second line should contain T numbers, specifying the conference for each team (1 or 2).

Example

Input

4 3
1 2
2 3
4 1
16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 16 15
16
2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 18
16
2 3 4 5 6 7 8 9 10 11 12 13 14 15 18 19
16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 16 19


Output

16 15 19 14 
2 2 2 1 1 1 2 1 1 2 1 1 1 2 2 1 1 1 1 

Note

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
const int inf = 2000000000;
const int N = 1000005;
vector<int> e[N], g[N];
int C[N], r[N], st[N], use[N], p[N], ans[N], color[N], s[N];
bool kun(int v, int c) {
  if (use[v] == c) return false;
  use[v] = c;
  for (int i = 0; i < e[v].size(); i++) {
    if (p[e[v][i]] == 0) {
      p[e[v][i]] = v;
      return true;
    }
  }
  for (int i = 0; i < e[v].size(); i++) {
    if (kun(e[v][i], c)) {
      p[e[v][i]] = v;
      return true;
    }
  }
  return false;
}
void dfs(int v, int c) {
  color[ans[v]] = c;
  for (int i = 0; i < g[v].size(); i++) {
    int to = g[v][i];
    if (color[ans[to]] == 0) {
      dfs(to, 3 - c);
    }
  }
}
int main() {
  srand(time(NULL));
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int q, w;
    cin >> q >> w;
    g[q].push_back(w);
    g[w].push_back(q);
  }
  for (int i = 1; i <= n; i++) {
    st[i] = g[i].size();
  }
  int T = 0;
  for (int i = 1; i <= n; i++) {
    int l;
    cin >> l;
    e[i].resize(l);
    for (int j = 0; j < l; j++) {
      cin >> e[i][j];
      T = max(T, e[i][j]);
    }
    random_shuffle(e[i].begin(), e[i].end());
  }
  for (int i = 1; i <= n; i++) {
    s[i] = i;
  }
  random_shuffle(s + 1, s + n + 1);
  queue<int> q;
  for (int i = 1; i <= n; i++) {
    q.push(s[i]);
    use[s[i]] = 1;
    color[i] = rand() % 2 + 1;
  }
  int TIME = 0;
  while (!q.empty()) {
    TIME++;
    if (TIME > 5e8) {
      break;
    }
    int v = q.front();
    if (r[v] < st[v] - r[v]) {
      r[v] = st[v] - r[v];
      color[v] = 3 - color[v];
      for (int i = 0; i < g[v].size(); i++) {
        int to = g[v][i];
        if (color[v] != color[to]) {
          r[to]++;
          if (!use[to] && r[to] < st[to] - r[to]) {
            use[to] = true;
            q.push(to);
          }
        } else {
          r[to]--;
        }
      }
    }
    use[v] = 0;
    q.pop();
  }
  bool gfl;
  for (int q = 0; q < 1000; q++) {
    for (int i = 1; i <= T; i++) {
      C[i] = rand() % 2 + 1;
    }
    gfl = true;
    for (int i = 1; i <= n; i++) {
      bool fl = false;
      for (int j = 0; j < e[i].size(); j++) {
        int to = e[i][j];
        if (C[to] == color[i]) {
          fl = true;
          ans[i] = to;
          break;
        }
      }
      if (!fl) {
        gfl = false;
        break;
      }
    }
    if (gfl) {
      break;
    }
  }
  if (!gfl) {
    return 1;
  }
  for (int i = 1; i <= n; i++) {
    cout << ans[i] << " ";
  }
  cout << "\n";
  for (int i = 1; i <= T; i++) {
    cout << C[i] << " ";
  }
}