#include <cstdio>  //{{{
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <algorithm>

#define ALL(c) (c).begin(), (c).end()
#define DUMP(x) std::cerr << #x << ':' << x << '\n';

typedef long long ll;
// clang-format off
template<typename T,typename U>inline bool chmax(T&x,U a){if(x>=a)return 0;x=a;return 1;}
template<typename T,typename U>inline bool chmin(T&x,U a){if(x<=a)return 0;x=a;return 1;}
inline int in(){int x;scanf("%d", &x);return x;}
// clang-format on
// }}}
//{{{ graph.hpp
#ifndef INCLUDE_GRAPH_HPP
#define INCLUDE_GRAPH_HPP
#include <vector>
#include <climits>
namespace orliv {
namespace graph {
struct Edge {
  typedef int weight_type;
  static constexpr weight_type INF =
      std::numeric_limits<weight_type>::max() - 100;

  int from, to;
  weight_type w;
  Edge(int from, int to, weight_type w = 1) : from(from), to(to), w(w) {}
  bool operator<(const Edge& rhs) const {
    if (w != rhs.w) return w > rhs.w;
    if (from != rhs.from) return from < rhs.from;
    return to < rhs.to;
  }
};

typedef Edge::weight_type Weight;
typedef std::vector<Edge> Edges;
typedef std::vector<Weight> Weights;
typedef std::vector<int> Path;
}
typedef std::vector<graph::Edges> Graph;
}
#endif
//}}}
//{{{ hl_decomposition.cc
#ifndef INCLUDE_GRAPH_HPP
#include "graph.hpp"
#endif

namespace orliv {
namespace graph {

struct HLDecomposition {
  const Graph& g;
  const int V;
  std::vector<int> par, ord, depth;
  std::vector<int> cluster;
  std::vector<Path> pathes;
  std::vector<int> path_idx;

  HLDecomposition(const Graph& g) : g(g), V(g.size()) {}

  void build(int root = 0) {
    ord.clear();
    ord.reserve(V);
    pathes.clear();
    par.assign(V, 0);
    depth.assign(V, 0);

    ord.emplace_back(root);
    par[root] = -1;
    for (int i = 0; i < ord.size(); i++) {
      int u = ord[i];
      for (const auto& e : g[u]) {
        int v = e.to;
        if (par[u] == v) continue;
        par[v] = u;
        depth[v] = depth[u] + 1;
        ord.emplace_back(v);
      }
    }
    decomposition();
  }
  int lca(int u, int v) const {
    while (cluster[u] != cluster[v]) {
      int head_u = pathes[cluster[u]][0];
      int head_v = pathes[cluster[v]][0];
      if (depth[head_u] > depth[head_v]) {
        std::swap(u, v);
        std::swap(head_v, head_u);
      }
      v = par[head_v];
    }
    return depth[u] < depth[v] ? u : v;
  }

 private:
  void decomposition() {
    std::vector<int> subtree_size(V, 1);
    for (int i = V - 1; i > 0; i--) {
      subtree_size[par[ord[i]]] += subtree_size[ord[i]];
    }
    cluster.assign(V, -1);
    for (int u : ord) {
      if (cluster[u] == -1) {
        cluster[u] = pathes.size();
        pathes.emplace_back();
      }
      pathes[cluster[u]].emplace_back(u);

      int max_subsize = -1, selected = -1;
      for (const auto& e : g[u]) {
        int v = e.to;
        if (par[u] == v) continue;
        if (max_subsize >= subtree_size[v]) continue;
        max_subsize = subtree_size[v];
        selected = v;
      }
      if (selected != -1) cluster[selected] = cluster[u];
    }
    path_idx.resize(V);
    for (const auto& path : pathes) {
      for (int i = 0; i < path.size(); i++) path_idx[path[i]] = i;
    }
  }
};
}
}
//}}}

using namespace std;

int main() {
  int N = in();
  orliv::Graph g(N);
  for (int i = 0; i < N; i++) {
    int k = in();
    for (int j = 0; j < k; j++) {
      int c = in();
      g[i].emplace_back(i, c);
      g[c].emplace_back(c, i);
    }
  }
  orliv::graph::HLDecomposition hl(g);
  hl.build(0);
  int q = in();
  for (int i = 0; i < q; i++) {
    int u = in(), v = in();
    cout << hl.lca(u, v) << endl;
  }
  return 0;
}

Measured memory_bytes: 16256