#include <bits/stdc++.h>
using namespace std;
using ll = long long;

/// --- LinkCutTree Library {{{ ///

template < class Monoid, class M_act >
struct LinkCutTree {
  using X = typename Monoid::T;
  using M = typename M_act::M;
  struct Splay;
  int n;

  // Splay sequence {{{
  struct Splay {
    int ch[2] = {-1, -1}, p = -1;
    vector< Splay > &data;
    int id;
    X val, accum;
    M lazy = M_act::identity(); ///////
    // BSTの大きさ
    // 実際の部分木の大きさ，ではない
    int sz = 1;
    bool isRoot() {
      return p == -1 || (data[p].ch[0] != id && data[p].ch[1] != id);
    }
    bool rev = false;
    // call before use
    void eval() {
      if (rev) {
        swap(ch[0], ch[1]);
        if (ch[0] != -1) data[ch[0]].rev ^= 1;
        if (ch[1] != -1) data[ch[1]].rev ^= 1;
        rev = false;
      }
      if (lazy != M_act::identity()) {
        val = M_act::actInto(lazy, 1, val);
        accum = M_act::actInto(lazy, sz, accum);
        for (int i = 0; i < 2; i++)
          if (ch[i] != -1) data[ch[i]].lazy = M_act::op(lazy, data[ch[i]].lazy);
        lazy = M_act::identity();
      }
    }
    void evalDown() {
      vector< int > b2t;
      int t = id;
      for (; !data[t].isRoot(); t = data[t].p) b2t.emplace_back(t);
      data[t].eval();
      while (b2t.size()) data[b2t.back()].eval(), b2t.pop_back();
      vector< int >().swap(b2t);
    }
    X accumulated(int a) {
      return a == -1 ? Monoid::identity() : data[a].accum;
    }
    int size(int a) { return a == -1 ? 0 : data[a].sz; }
    // call after touch
    void prop() {
      if (ch[0] != -1) data[ch[0]].eval(); ////
      if (ch[1] != -1) data[ch[1]].eval(); ////
      sz = size(ch[0]) + 1 + size(ch[1]);
      accum =
          Monoid::op(Monoid::op(accumulated(ch[0]), val), accumulated(ch[1]));
    }
    Splay(vector< Splay > &data, const X &val)
        : data(data), val(val), accum(val) {}
    int rotate(bool R) {
      int t = ch[!R];
      if ((ch[!R] = data[t].ch[R]) != -1) data[ch[!R]].p = id;
      data[t].ch[R] = id; ////
      if ((data[t].p = p) != -1) {
        if (data[data[t].p].ch[0] == id) data[data[t].p].ch[0] = t;
        if (data[data[t].p].ch[1] == id) data[data[t].p].ch[1] = t;
      }
      p = t; //////
      prop();
      data[t].prop();
      return t;
    }
    // bottom-up
    int splay() {
      evalDown();
      while (!this->isRoot()) {
        int q = p;
        if (data[q].isRoot()) {
          data[q].rotate(data[q].ch[0] == id);
        } else {
          int r = data[q].p;
          bool V = data[r].ch[0] == q;
          if (data[q].ch[!V] == id)
            data[r].rotate(V);
          else
            data[q].rotate(!V);
          data[p].rotate(V); ///////
        }
      }
      return id;
    }
  };
  // }}}

  vector< Splay > data;
  LinkCutTree() : n(0) {}
  LinkCutTree(int n, const X &initial = Monoid::identity())
      : n(n), data(n, Splay(data, initial)) {
    for (int i = 0; i < n; i++) data[i].id = i;
  }
  const X &get(int i) {
    data[i].evalDown();
    return data[i].val;
  }
  void set(int i, X val) {
    data[i].splay();
    data[i].val = val;
    data[i].prop();
  }

  // LinkCutTree implementation

  int expose(int i) {
    int prv = -1, now = i;
    for (; now != -1; prv = now, now = data[now].p) {
      data[now].splay();
      data[now].ch[1] = prv;
      data[now].prop();
    }
    data[i].splay(); /////
    return prv;
  }
  void cut(int c) {
    expose(c);
    int s = data[c].ch[0];
    data[c].ch[0] = -1;
    data[c].prop();
    data[s].p = -1;
  }
  void link(int p, int c) {
    expose(p);
    expose(c);

    static const struct CannotLinkSameNode {
    } ex;
    if (data[p].p != -1) throw ex;

    data[c].p = p;

    data[p].ch[1] = c;
    data[p].prop();
  }
  void evert(int x) {
    expose(x);
    data[x].rev = true;
  }
  bool same(int a, int b) {
    if (a == b) return true;
    expose(a);
    expose(b);
    return data[a].p != -1;
  }
  int lca(int a, int b) {
    expose(a);
    int r = expose(b);
    return r == -1 ? b : r;
  }
  void act(int a, int b, const M &m) {
    static const struct CannotActAnotherNode {
    } ex;
    if (!same(a, b)) throw ex;
    // evert(a);
    expose(b);
    data[b].lazy = M_act::op(m, data[b].lazy);
  }
  X query(int a) {
    // static const struct CannotQueryAnotherNode {
    // } ex;
    // if (!same(a, b)) throw ex;
    // evert(a);
    expose(a);
    return data[a].accum;
  }
};

/// }}}--- ///

// Monoid, M_act expamles {{{

struct Nothing {
  using T = char;
  using M = char;
  static constexpr T op(const T &, const T &) { return 0; }
  static constexpr T identity() { return 0; }
  template < class S, class X >
  static constexpr X actInto(const M &, S, const X &x) {
    return x;
  }
};

// }}}

int main() {
  std::ios::sync_with_stdio(false), std::cin.tie(0);
  int n;
  cin >> n;
  LinkCutTree< Nothing, Nothing > lc(n); ////
  for (int i = 0; i < n; i++) {
    int k;
    cin >> k;
    while(k--) {
      int a;
      cin >> a;
      lc.evert(a);
      lc.link(i, a);
    }
  }
  // lc.evert(0);
  int q;
  cin >> q;
  while (q--) {
    int a, b;
    cin >> a >> b;
    cout << lc.lca(a, b) << endl;
  }
  return 0;
}




Measured memory_bytes: 7368