#include <bits/stdc++.h>
using namespace std;
int read() {
  char ch = getchar();
  int x = 0, ff = 1;
  while (ch < '0' || ch > '9') {
    if (ch == '-') ff = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
  return x * ff;
}
void write(int aa) {
  if (aa < 0) putchar('-'), aa = -aa;
  if (aa > 9) write(aa / 10);
  putchar('0' + aa % 10);
  return;
}
int n, m, root, cnt;
int jl[100005], jr[100005];
int top, zhan[200005], dian[200005];
vector<int> lu[100005];
struct node {
  int ff, sumz, sumy;
  int val, mn, mx, lz;
  int son[2], fa;
} tt[200005];
void up(int rt) {
  tt[rt].sumy = 0;
  tt[rt].sumz = 0;
  int L = tt[tt[rt].son[0]].sumz, R = tt[tt[rt].son[1]].sumy;
  if (tt[rt].ff == 1)
    L++;
  else
    R++;
  if (L <= R)
    tt[rt].sumy += R - L;
  else
    tt[rt].sumz += L - R;
  tt[rt].sumy += tt[tt[rt].son[0]].sumy;
  tt[rt].sumz += tt[tt[rt].son[1]].sumz;
  tt[rt].mn = min(tt[rt].val, min(tt[tt[rt].son[0]].mn, tt[tt[rt].son[1]].mn));
  tt[rt].mx = max(tt[rt].val, max(tt[tt[rt].son[0]].mx, tt[tt[rt].son[1]].mx));
  return;
}
void push(int rt) {
  if (tt[rt].lz) {
    if (tt[rt].son[0]) {
      tt[tt[rt].son[0]].lz += tt[rt].lz;
      tt[tt[rt].son[0]].mn += tt[rt].lz;
      tt[tt[rt].son[0]].mx += tt[rt].lz;
      tt[tt[rt].son[0]].val += tt[rt].lz;
    }
    if (tt[rt].son[1]) {
      tt[tt[rt].son[1]].lz += tt[rt].lz;
      tt[tt[rt].son[1]].mn += tt[rt].lz;
      tt[tt[rt].son[1]].mx += tt[rt].lz;
      tt[tt[rt].son[1]].val += tt[rt].lz;
    }
    tt[rt].lz = 0;
  }
  return;
}
void dfs(int rt, int dep) {
  tt[++cnt].val = dep;
  tt[cnt].ff = 1;
  dian[cnt] = rt;
  jl[rt] = cnt;
  int len = lu[rt].size();
  for (int i = 0; i < len; ++i) dfs(lu[rt][i], dep + 1);
  tt[++cnt].val = dep;
  tt[cnt].ff = -1;
  dian[cnt] = rt;
  jr[rt] = cnt;
  return;
}
int bt(int fa, int ll, int rr) {
  if (ll > rr) return 0;
  int mid = (ll + rr) >> 1;
  tt[mid].fa = fa;
  tt[mid].son[0] = bt(mid, ll, mid - 1);
  tt[mid].son[1] = bt(mid, mid + 1, rr);
  up(mid);
  return mid;
}
void update(int x) {
  int y = tt[x].fa, z = tt[y].fa, ff = (tt[y].son[1] == x);
  tt[y].fa = x;
  tt[x].fa = z;
  if (tt[x].son[ff ^ 1]) tt[tt[x].son[ff ^ 1]].fa = y;
  if (z) tt[z].son[tt[z].son[1] == y] = x;
  tt[y].son[ff] = tt[x].son[ff ^ 1];
  tt[x].son[ff ^ 1] = y;
  up(y);
  up(x);
  return;
}
void bh(int x) {
  int now = x;
  while (now) zhan[++top] = now, now = tt[now].fa;
  while (top) push(zhan[top]), top--;
  while (tt[x].fa) {
    int y = tt[x].fa, z = tt[y].fa;
    if (z) (tt[z].son[1] == y) ^ (tt[y].son[1] == x) ? update(x) : update(y);
    update(x);
  }
  root = x;
  return;
}
int pan(int rt, int mx) { return tt[rt].mn <= mx && tt[rt].mx >= mx; }
int find(int now, int mx) {
  push(now);
  while (tt[now].val != mx || pan(tt[now].son[1], mx) == 1) {
    now = tt[now].son[pan(tt[now].son[1], mx)];
    push(now);
  }
  return now;
}
int main() {
  n = read(), m = read();
  tt[0].mn = n + 1;
  tt[0].mx = -1;
  for (int i = 1; i <= n; ++i) {
    int x = read();
    for (int j = 1; j <= x; ++j) {
      int y = read();
      lu[i].push_back(y);
    }
  }
  dfs(1, 0);
  root = bt(0, 1, cnt);
  while (m--) {
    int flag = read();
    if (flag == 1) {
      int x = read(), y = read(), ans = 0;
      if (x == y) {
        puts("0");
        continue;
      }
      x = jr[x];
      y = jl[y];
      bh(y);
      bh(x);
      if (tt[y].fa != x) update(y);
      int L = 0, R = 0;
      if (tt[x].son[0] == y)
        L = tt[tt[y].son[1]].sumz, R = tt[tt[y].son[1]].sumy;
      else
        L = tt[tt[y].son[0]].sumz + 1, R = tt[tt[y].son[0]].sumy + 1;
      if (!L || !R)
        ans = abs(tt[x].val - tt[y].val);
      else
        ans = L + R;
      write(ans);
      puts("");
    } else if (flag == 2) {
      int x = read(), y = 0, h = read(), rt1 = 0, rt2 = 0, RT = 0;
      y = jr[x];
      x = jl[x];
      bh(x);
      rt1 = tt[x].son[0];
      if (rt1) tt[rt1].fa = 0, tt[x].son[0] = 0, up(x);
      while (tt[rt1].son[1]) rt1 = tt[rt1].son[1];
      bh(rt1);
      RT = jr[dian[find(rt1, tt[x].val - h)]];
      bh(y);
      rt2 = tt[y].son[1];
      if (rt2) tt[rt2].fa = 0, tt[y].son[1] = 0, up(y);
      if (rt1)
        tt[rt1].son[1] = rt2, tt[rt2].fa = rt1, up(rt1);
      else
        rt1 = rt2;
      bh(RT);
      rt1 = tt[RT].son[0];
      while (tt[rt1].son[1]) rt1 = tt[rt1].son[1];
      if (rt1) bh(rt1);
      if (rt1 && tt[RT].fa != rt1) update(RT);
      tt[RT].son[0] = y;
      tt[y].fa = RT;
      tt[y].lz -= h - 1, tt[y].mn -= h - 1;
      tt[y].val -= h - 1, tt[y].mx -= h - 1;
      up(RT);
      if (rt1) up(rt1);
      bh(y);
    } else {
      int x = read();
      x = find(root, x);
      bh(x);
      write(dian[x]), puts("");
    }
  }
  return 0;
}
