// Original C++ solution (slower):
#include<bits/stdc++.h>



using namespace std;



template< typename Monoid >

struct DisjointSparseTable {

  using F = function< Monoid(Monoid, Monoid) >;

  const F &f;

  vector< vector< Monoid > > st;



  DisjointSparseTable(const vector< Monoid > &v, const F &f) : f(f) {



    int b = 0;

    while((1 << b) <= v.size()) ++b;

    st.resize(b, vector< Monoid >(v.size(), Monoid()));

    for(int i = 0; i < v.size(); i++) st[0][i] = v[i];

    for(int i = 1; i < b; i++) {

      int shift = 1 << i;

      for(int j = 0; j < v.size(); j += shift << 1) {

        int t = min(j + shift, (int) v.size());

        st[i][t - 1] = v[t - 1];

        for(int k = t - 2; k >= j; k--) st[i][k] = f(v[k], st[i][k + 1]);

        if(v.size() <= t) break;

        st[i][t] = v[t];

        int r = min(t + shift, (int) v.size());

        for(int k = t + 1; k < r; k++) st[i][k] = f(st[i][k - 1], v[k]);

      }

    }

  }



  Monoid query(int l, int r) {

    if(l >= --r) return st[0][l];

    int p = 31 - __builtin_clz(l ^ r);

    return f(st[p][l], st[p][r]);

  }

};



using Pi = pair< int, int >;



vector< int > g[100000];

vector< Pi > depth;

int rev[100000];



void dfs(int idx, int dep) {

  rev[idx] = (int) depth.size();

  depth.emplace_back(dep, idx);

  for(auto &to : g[idx]) {

    dfs(to, dep + 1);

    depth.emplace_back(dep, idx);

  }

}



int main() {

  int N, Q;

  scanf("%d", &N);

  for(int i = 0; i < N; i++) {

    int k;

    scanf("%d", &k);

    for(int j = 0; j < k; j++) {

      int c;

      scanf("%d", &c);

      g[i].push_back(c);

    }

  }

  dfs(0, -1);

  auto f = [](const Pi &a, const Pi &b) { return min(a, b); };

  DisjointSparseTable< Pi > beet(depth, f);

  scanf("%d", &Q);

  for(int i = 0; i < Q; i++) {

    int a, b;

    scanf("%d %d", &a, &b);

    auto p = minmax(rev[a], rev[b]);

    printf("%d\n", beet.query(p.first, p.second).second);

  }

}




// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>



#include <utility>



using namespace std;



using int64 = long long;

const int mod = 1e9 + 7;

//const int mod = 998244353;



const int64 infll = (1LL << 62) - 1;

const int inf = (1 << 30) - 1;



struct IoSetup {

  IoSetup() {

    cin.tie(nullptr);

    ios::sync_with_stdio(false);

    cout << fixed << setprecision(10);

    cerr << fixed << setprecision(10);

  }

} iosetup;





template< typename T1, typename T2 >

ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {

  os << p.first << " " << p.second;

  return os;

}



template< typename T1, typename T2 >

istream &operator>>(istream &is, pair< T1, T2 > &p) {

  is >> p.first >> p.second;

  return is;

}



template< typename T >

ostream &operator<<(ostream &os, const vector< T > &v) {

  for(int i = 0; i < (int) v.size(); i++) {

    os << v[i] << (i + 1 != v.size() ? " " : "");

  }

  return os;

}



template< typename T >

istream &operator>>(istream &is, vector< T > &v) {

  for(T &in : v) is >> in;

  return is;

}



template< typename T1, typename T2 >

inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }



template< typename T1, typename T2 >

inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }



template< typename T = int64 >

vector< T > make_v(size_t a) {

  return vector< T >(a);

}



template< typename T, typename... Ts >

auto make_v(size_t a, Ts... ts) {

  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));

}



template< typename T, typename V >

typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {

  t = v;

}



template< typename T, typename V >

typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {

  for(auto &e : t) fill_v(e, v);

}



template< typename F >

struct FixPoint : F {

  FixPoint(F &&f) : F(forward< F >(f)) {}



  template< typename... Args >

  decltype(auto) operator()(Args &&... args) const {

    return F::operator()(*this, forward< Args >(args)...);

  }

};



template< typename F >

inline decltype(auto) MFP(F &&f) {

  return FixPoint< F >{forward< F >(f)};

}



template< typename T = int >

struct Edge {

  int from, to;

  T cost;

  int idx;



  Edge() = default;



  Edge(int from, int to, T cost = 1, int idx = -1) : from(from), to(to), cost(cost), idx(idx) {}



  operator int() const { return to; }

};



template< typename T = int >

struct Graph {

  vector< vector< Edge< T > > > g;

  int es;



  Graph() = default;



  explicit Graph(int n) : g(n), es(0) {}



  size_t size() const {

    return g.size();

  }



  void add_directed_edge(int from, int to, T cost = 1) {

    g[from].emplace_back(from, to, cost, es++);

  }



  void add_edge(int from, int to, T cost = 1) {

    g[from].emplace_back(from, to, cost, es);

    g[to].emplace_back(to, from, cost, es++);

  }



  void read(int M, int padding = -1, bool weighted = false, bool directed = false) {

    for(int i = 0; i < M; i++) {

      int a, b;

      cin >> a >> b;

      a += padding;

      b += padding;

      T c = T(1);

      if(weighted) cin >> c;

      if(directed) add_directed_edge(a, b, c);

      else add_edge(a, b, c);

    }

  }

};



template< typename T >

struct DoublingLowestCommonAncestor : Graph< T > {

public:

  using Graph< T >::g;

  vector< int > dep;

  vector< T > sum;

  vector< vector< int > > table;

  const int LOG;



  explicit DoublingLowestCommonAncestor(int n)

      : LOG(32 - __builtin_clz(g.size())), Graph< T >(n) {}



  explicit DoublingLowestCommonAncestor(const Graph< T > &g)

      : LOG(32 - __builtin_clz(g.size())), Graph< T >(g) {}



  void build() {

    dep.assign(g.size(), 0);

    sum.assign(g.size(), 0);

    table.assign(LOG, vector< int >(g.size(), -1));

    dfs(0, -1, 0);

    for(int k = 0; k + 1 < LOG; k++) {

      for(int i = 0; i < table[k].size(); i++) {

        if(table[k][i] == -1) table[k + 1][i] = -1;

        else table[k + 1][i] = table[k][table[k][i]];

      }

    }

  }



  int lca(int u, int v) {

    if(dep[u] > dep[v]) swap(u, v);

    for(int i = LOG - 1; i >= 0; i--) {

      if(((dep[v] - dep[u]) >> i) & 1) v = table[i][v];

    }

    if(u == v) return u;

    for(int i = LOG - 1; i >= 0; i--) {

      if(table[i][u] != table[i][v]) {

        u = table[i][u];

        v = table[i][v];

      }

    }

    return table[0][u];

  }



  T dist(int u, int v) {

    return sum[u] + sum[v] - 2 * sum[lca(u, v)];

  }



private:

  void dfs(int idx, int par, int d) {

    table[0][idx] = par;

    dep[idx] = d;

    for(auto &to : g[idx]) {

      if(to != par) {

        sum[to] = sum[idx] + to.cost;

        dfs(to, idx, d + 1);

      }

    }

  }

};





int main() {

  int N, Q;

  cin >> N;

  DoublingLowestCommonAncestor< int > dlca(N);

  for(int i = 0; i < N; i++) {

    int k;

    cin >> k;

    for(int j = 0; j < k; j++) {

      int c;

      cin >> c;

      dlca.add_edge(i, c);

    }

  }

  dlca.build();

  cin >> Q;

  for(int i = 0; i < Q; i++) {

    int u, v;

    cin >> u >> v;

    cout << dlca.lca(u, v) << "\n";

  }

}


// Fastest known solution for this problem: