#include <algorithm>
#include <assert.h>
#include <cstdlib>
#include <vector>

template <typename T>
struct RMQ {
  using Index = int;
  using BitIndex = int;

  const std::vector<T>& A;
  const int N, S, L, LG_L;

  std::vector<int> lg;
  BitIndex* const small;
  Index* const large;

  bool f(Index a, Index b) const {
    if (A[a] != A[b]) return A[a] < A[b];
    return a < b;
  }
  RMQ(const std::vector<T>& A) : RMQ(A, A.size()) {}
  Index query(Index l, Index r) const {
    const int a = l / S, b = r / S;
    if (a == b) return query_small(l, r);

    Index ans = F(query_small(l, a * S + (S - 1)), query_small(b * S, r));
    if (a + 1 <= b - 1) ans = F(ans, query_large(a + 1, b - 1));
    return ans;
  }
  ~RMQ() {
    std::free(small);
    std::free(large);
  }
private:
  inline Index F(Index a, Index b) const { return f(a, b) ? a : b; }

  RMQ(const std::vector<T>& A, int N) : RMQ(A, N, std::__lg(N) + 1) {}
  RMQ(const std::vector<T>& A, int N, int S) : RMQ(A, N, S, (N + S - 1) / S) {}
  RMQ(const std::vector<T>& A, int N, int S, int L) : RMQ(A, N, S, L, std::__lg(L) + 1) {}
  RMQ(const std::vector<T>& A, int N, int S, int L, int LG_L)
      : A(A), N(N), S(S), L(L), LG_L(LG_L), lg(1 << S), small((BitIndex*)std::malloc(N * sizeof(BitIndex))), large((Index*)std::malloc(L * LG_L * sizeof(Index))) {
    assert(small != nullptr);
    assert(large != nullptr);
    for (int i = 1, sz = lg.size(); i < sz; i++) {
      lg[i] = std::__lg(i);
    }
    for (int li = 0; li < L; li++) {
      int i = li * S;
      large[li * LG_L + 0] = i;
      for (int si = 0; si < S && i + si < N; si++) {
        large[li * LG_L + 0] = F(large[li * LG_L + 0], i + si);
      }
    }
    for (int x = 0; x < LG_L - 1; x++) {
      for (int li = 0; li + (1 << x) < L; li++) {
        large[li * LG_L + x + 1] = F(large[li * LG_L + x], large[(li + (1 << x)) * LG_L + x]);
      }
    }
    Index st[32];
    for (int li = 0; li < L; li++) {
      int i = li * S;
      int sti = 0;
      for (int si = 0; si < S && i + si < N; si++) {
        while (sti > 0 && f(i + si, st[sti - 1])) --sti;
        small[i + si] |= 1 << si;
        if (sti > 0) small[i + si] |= small[st[sti - 1]];
        st[sti] = i + si;
        ++sti;
      }
    }
  }
  inline int ntz(int x) const { return lg[x & -x]; }
  inline int bitmask(int l, int r) const { return ((1 << (r - l + 1)) - 1) << l; }
  inline Index query_small(Index l, Index r) const { return (l - l % S) + ntz(small[r] & bitmask(l % S, r % S)); }
  inline Index query_large(Index l, Index r) const {
    int x = lg[r - l + 1];
    return F(large[l * LG_L + x], large[(r - (1 << x) + 1) * LG_L + x]);
  }
};
#include <vector>
#include <stack>

struct EulerTour {
  using tree_type = std::vector<std::vector<int>>;
  tree_type T;
  std::vector<int> id, depth;
  std::vector<int> ord;

  EulerTour(int N) : T(N), ord(N) {}

  void add_edge(int s, int t) {
    T[s].push_back(t);
    T[t].push_back(s);
  }

  void build(int root) {
    id.reserve(T.size() * 3);
    depth.reserve(T.size() * 3);
    traverse(root);
    id.shrink_to_fit();
    depth.shrink_to_fit();
  }

  void traverse(int u, int p=-1, int d=0) {
#if 0
    struct Frame {
      int u, p, d;
      int i = 0;
      Frame(int u, int p, int d) : u(u), p(p), d(d) {}
    };
    std::stack<Frame> s;

    s.emplace(u, p, d);
    while (!s.empty()) {
      auto& f = s.top();
      if (f.i == 0) ord[f.u] = id.size();
      id.push_back(f.u);
      depth.push_back(f.d);

      bool call = false;
      while (f.i < T[f.u].size()) {
        int v = T[f.u][f.i];
        ++f.i;
        if (v != f.p) {
          s.emplace(v, f.u, f.d + 1);
          call = true;
          break;
        }
      }
      if (!call) s.pop();
    }
#else
    ord[u] = id.size();
    id.push_back(u);
    depth.push_back(d);
    for (int v : T[u]) {
      if (v == p) continue;
      traverse(v, u, d + 1);
      id.push_back(u);
      depth.push_back(d);
    }
#endif
  }
};
#include <vector>

struct LCA {
  EulerTour euler_tour;
  const RMQ<int> rmq;

  LCA(EulerTour&& euler_tour) : euler_tour(euler_tour), rmq(euler_tour.depth) {}

  int query(int u, int v) const {
    int l = euler_tour.ord[u];
    int r = euler_tour.ord[v];
    if (r < l) std::swap(r, l);
    int x = rmq.query(l, r);
    return euler_tour.id[x];
  }
};

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

#define mygc(c) (c) = getchar_unlocked()
#define mypc(c) putchar_unlocked(c)

template<typename T=int>
T rd(){T x=0,m=0,k;for(;;){mygc(k);if(k=='-'){m=1;break;}if('0'<=k&&k<='9'){x=k-'0';break;}}for(;;){mygc(k);if(k<'0'||'9'<k)break;x=x*10+k-'0';}return x;}
template<typename T=int>
void wr(T x,char c='\n'){int s=0,m=0;char b[32];if(x<0)m=1,x=-x;for(;x;x/=10)b[s++]=x%10;if(!s)b[s++]=0;if(m)mypc('-');for(;s--;)mypc(b[s]+'0');mypc(c);}

int main() {
  // std::freopen("in_large.txt", "r", stdin);
  int N = rd();
  EulerTour et(N);
  for (int i = 0; i < N; i++) {
    int k = rd();
    et.T[i].reserve(k);
    for (int j = 0; j < k; j++) {
      et.T[i].push_back(rd());
    }
  }
  et.build(0);
  LCA lca(move(et));
  int Q = rd();
  for (int i = 0; i < Q; i++) {
    int u = rd(), v = rd();
    wr(lca.query(u, v));
  }
  return 0;
}

Measured memory_bytes: 23624