#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200000;
struct Splay {
  struct node {
    node *fa, *ch[2];
    int num, key, mx, mn, tg;
  } pl[2 * MAXN + 5], *root, *NIL;
  Splay() {
    root = NIL = &pl[0];
    NIL->ch[0] = NIL->ch[1] = NIL->fa = NIL;
    NIL->mx = -MAXN, NIL->mn = MAXN, NIL->tg = 0;
  }
  void set_child(node *x, node *y, int d) {
    if (x != NIL) x->ch[d] = y;
    if (y != NIL) y->fa = x;
  }
  void pushdown(node *x) {
    if (x->tg) {
      if (x->ch[0] != NIL)
        x->ch[0]->key += x->tg, x->ch[0]->mx += x->tg, x->ch[0]->mn += x->tg,
            x->ch[0]->tg += x->tg;
      if (x->ch[1] != NIL)
        x->ch[1]->key += x->tg, x->ch[1]->mx += x->tg, x->ch[1]->mn += x->tg,
            x->ch[1]->tg += x->tg;
      x->tg = 0;
    }
  }
  void pushup(node *x) {
    x->mn = min(x->key, min(x->ch[0]->mn, x->ch[1]->mn));
    x->mx = max(x->key, max(x->ch[0]->mx, x->ch[1]->mx));
  }
  void rotate(node *x) {
    node *y = x->fa;
    int d = (y->ch[1] == x);
    pushdown(y), pushdown(x);
    if (y->fa != NIL)
      set_child(y->fa, x, y->fa->ch[1] == y);
    else
      x->fa = y->fa;
    set_child(y, x->ch[!d], d);
    set_child(x, y, !d);
    if (y == root) root = x;
    pushup(y);
  }
  void splay(node *x, node *rt) {
    pushdown(x);
    while (x->fa != rt) {
      node *y = x->fa;
      if (y->fa == rt)
        rotate(x);
      else {
        if ((y->fa->ch[1] == y) == (y->ch[1] == x))
          rotate(y);
        else
          rotate(x);
        rotate(x);
      }
    }
    pushup(x);
  }
  void debug(node *x) {
    if (x == NIL) return;
    pushdown(x);
    debug(x->ch[0]);
    printf("%d : %d %d %d | %d %d\n", x - pl, x->ch[0] - pl, x->ch[1] - pl,
           x->fa - pl, x->num, x->key);
    debug(x->ch[1]);
  }
  int dist(node *x, node *y) {
    if (x == y) return 0;
    splay(x, NIL), splay(y, root);
    if (x->ch[0] == y) {
      int d = min(min(x->key, y->key), x->ch[0]->ch[1]->mn);
      return x->key + y->key - 2 * d;
    } else {
      int d = min(min(x->key, y->key), x->ch[1]->ch[0]->mn);
      return x->key + y->key - 2 * d;
    }
  }
  node *query(node *x, int d) {
    pushdown(x);
    if (x->ch[1]->mn <= d && d <= x->ch[1]->mx)
      return query(x->ch[1], d);
    else if (x->key == d) {
      splay(x, NIL);
      return x;
    } else
      return query(x->ch[0], d);
  }
  node *prev(node *x, node *rt) {
    splay(x, rt);
    node *ret = x->ch[0];
    while (ret->ch[1] != NIL) ret = ret->ch[1];
    splay(ret, rt);
    return ret;
  }
  node *next(node *x, node *rt) {
    splay(x, rt);
    node *ret = x->ch[1];
    while (ret->ch[0] != NIL) ret = ret->ch[0];
    splay(ret, rt);
    return ret;
  }
} T;
Splay::node *fir[MAXN + 5], *bac[MAXN + 5];
int n, m, root;
vector<int> G[MAXN + 5];
void addedge(int u, int v) { G[u].push_back(v); }
int dep[MAXN + 5], dfn[2 * MAXN + 5], dcnt;
void newnode(Splay::node *nw, int x, int k) {
  nw->ch[0] = nw->ch[1] = nw->fa = T.NIL;
  nw->num = x, nw->key = nw->mn = nw->mx = k, nw->tg = 0;
}
void dfs(int x) {
  dfn[++dcnt] = x, fir[x] = bac[x] = &T.pl[dcnt],
  newnode(&T.pl[dcnt], x, dep[x]);
  for (int i = 0; i < G[x].size(); i++) {
    int p = G[x][i];
    dep[p] = dep[x] + 1, dfs(p);
    dfn[++dcnt] = x, bac[x] = &T.pl[dcnt], newnode(&T.pl[dcnt], x, dep[x]);
  }
}
Splay::node *build(int l, int r) {
  if (l > r) return T.NIL;
  int mid = (l + r) >> 1;
  Splay::node *p = &T.pl[mid];
  p->ch[0] = build(l, mid - 1);
  if (p->ch[0] != T.NIL) p->ch[0]->fa = p;
  p->ch[1] = build(mid + 1, r);
  if (p->ch[1] != T.NIL) p->ch[1]->fa = p;
  T.pushup(p);
  return p;
}
bool tag[MAXN + 5];
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) {
    int l;
    scanf("%d", &l);
    for (int j = 1; j <= l; j++) {
      int x;
      scanf("%d", &x);
      addedge(i, x);
      tag[x] = true;
    }
  }
  for (int i = 1; i <= n; i++)
    if (!tag[i]) root = i;
  newnode(&T.pl[++dcnt], 0, -1), dfs(root), newnode(&T.pl[++dcnt], 0, -1);
  T.root = build(1, dcnt);
  for (int i = 1; i <= m; i++) {
    int op;
    scanf("%d", &op);
    if (op == 1) {
      int v, u;
      scanf("%d%d", &v, &u);
      printf("%d\n", T.dist(fir[v], fir[u]));
    } else if (op == 2) {
      int v, h;
      scanf("%d%d", &v, &h);
      T.splay(fir[v], T.NIL);
      Splay::node *u = T.query(fir[v]->ch[0], fir[v]->key - h);
      Splay::node *l = T.prev(fir[v], T.NIL), *r = T.next(bac[v], T.root);
      if (bac[l->num] == r) bac[l->num] = l;
      T.set_child(l, r->ch[1], 1);
      Splay::node *p = r->ch[0];
      newnode(r, u->num, u->key), r->ch[0] = p;
      r->tg += 1 - h, T.pushdown(r), T.pushup(r);
      T.next(bac[u->num], T.NIL), T.splay(bac[u->num], T.root);
      bac[u->num] = r;
      T.set_child(T.root->ch[0], r, 1);
    } else if (op == 3) {
      int k;
      scanf("%d", &k);
      printf("%d\n", T.query(T.root, k)->num);
    }
  }
  return 0;
}
