#pragma GCC optimize ("O3")

#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include <prettyprint.hpp>
#define debug(...)  cerr << "[" << #__VA_ARGS__ << "]: ", d_err(__VA_ARGS__);
#else
#define debug(...) 83;
#endif

void d_err() {
    cerr << endl;
}

template <typename H, typename... T>
void d_err(H h, T... t) {
    cerr << h << " ";
    d_err(t...);
}

template <typename T>
void print(T x) {
    cout << x << endl;
}

#define ALL(x) (x).begin(), (x).end()
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define REVFOR(i, m, n) for (int i = (n - 1); i >= (m); --i)
#define REP(i, n) FOR(i, 0, n)
#define REVREP(i, n) REVFOR(i, 0, n)
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define bcnt __builtin_popcountll

typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<ll,ll> Pll;
typedef pair<int,int> Pin;

ll INF = 1e16;
int inf = 1e9;
ll MOD = 1e9+7;

// by RMQ
struct LCA {
    typedef pair<ll, int> ST;  // depth, index

    vector<ST> E;
    vector<ll> O, depth;
    vector<vi> to;

    struct SegTree {
        int N;
        vector<ST> dat;

        int get_n(int n) {
            int ret = 1;
            while (ret < n) ret <<= 1;

            return ret;
        }

        SegTree() : N(0) {}

        // {depth, index}
        explicit SegTree(const vector<ST> &v) {
            N = get_n(v.size());
            dat.resize(2 * N - 1, {INF, inf});

            REP(i, v.size()) dat[N + i - 1] = v[i];
            for (int i = N - 2; i > -1; --i) dat[i] = _op(dat[2 * i + 1], dat[2 * i + 2]);
        }

        ST _op(const ST& a, const ST& b) {
            if (a.fi > b.fi) return b;
            return a;
        }

        void _up(ST &a, const ST& b) {
            a = b;
        }

        void update(int i, ST v) {
            i += N - 1;
            _up(dat[i], v);

            while (i > 0) {
                i = (i - 1) / 2;
                dat[i] = _op(dat[2 * i + 1], dat[2 * i + 2]);
            }
        }

        // query for [a, b), k: current node id, [l, r): current range.
        ST query(int a, int b, int k = 0, int l = 0, int r = -1) {
            if (r < 0) r = N;

            if (b <= l || r <= a) return {INF, inf};
            if (a <= l && r <= b) return dat[k];

            int mid = (l + r) / 2;
            ST c1 = query(a, b, 2 * k + 1, l, mid);
            ST c2 = query(a, b, 2 * k + 2, mid, r);

            return _op(c1, c2);
        }
    } seg;

    LCA(int n = 0): to(n), O(n, -1), depth(n) {};

    void add_edge(int a, int b) {
        to[a].pb(b);
        to[b].pb(a);
    }

    void init(int root) {
        dfs(root); // euler tour
        seg = SegTree(E);
    }

    ST query(int a, int b) {
        int c = O[a], d = O[b];
        if (c > d) swap(c, d);

        return seg.query(c, d + 1); // return LCA's depth from root
    }

    void dfs(int v, int p = -1, int d = 0) {
        E.eb(d, v);
        depth[v] = d;
        if(O[v] == -1) O[v] = E.size() - 1;

        for(int u : to[v]) {
            if (u == p) continue;
            dfs(u, v, d + 1);
            E.eb(d, v);
        }
    }
};

//http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_5_C&lang=ja
int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);

    int n; cin >> n;

    LCA g(n);

    REP(i, n) {
        int k; cin >> k;
        REP(j, k) {
            int c; cin >> c;
            g.add_edge(i, c);
        }
    }

    g.init(0);

    debug(g.depth, g.E)

    int q; cin >> q;
    REP(i, q) {
        int u, v; cin >> u >> v;

        print(g.query(u, v).second);
    }
}


Measured memory_bytes: 24584