#include <bits/stdc++.h>

#define REP(i,n) for (int i=0;i<(n);++i)

using namespace std;

struct edge {
    typedef size_t weight_type;

    size_t m_to;

    edge(size_t to) : m_to(to) { }

    inline size_t to() const { return m_to; }

    inline weight_type weight() const { return 1; }

    friend std::ostream& operator<<(std::ostream &os, const edge &e) {
        os << "{ to: " << e.m_to << " }";
        return os;
    }
};

template <class Edge>
struct graph {
    using edge_type = Edge;

    const size_t m_n_vertices;
    std::vector<std::vector<edge_type>> m_edges;

    graph(size_t n_vertices) : m_n_vertices(n_vertices), m_edges(n_vertices) { }

    inline size_t n_vertices() const { return m_n_vertices; }

    inline void add_edge(size_t from, size_t to, typename edge_type::weight_type weight) {
        m_edges[from].emplace_back(to, weight);
    }

    inline void add_edge(size_t from, size_t to) {
        m_edges[from].push_back(to);
    }

    inline void add_edge(size_t from, const edge_type &e) {
        m_edges[from].emplace_back(e);
    }

    inline void add_biedge(size_t v0, size_t v1, typename edge_type::weight_type weight) {
        m_edges[v0].emplace_back(v1, weight);
        m_edges[v1].emplace_back(v0, weight);
    }

    inline void add_biedge(size_t v0, size_t v1) {
        m_edges[v0].push_back(v1);
        m_edges[v1].push_back(v0);
    }

    inline std::vector<edge_type> edges_from(size_t v) const {
        return m_edges[v];
    }
};

// N > 1
class lowest_common_ancestor {

    size_t log2_max_height; // floor(log2(max_height))
    std::vector<std::vector<size_t>> parent;
    std::vector<size_t> depth;

    size_t n_th_parent(size_t u, size_t n) {
        for (size_t i = 0; (1 << i) <= n; ++i) {
            if (n & (1 << i)) {
                u = parent[u][i];
            }
        }
        return u;
    }

public:

    // g is a tree
    template <class Graph>
    lowest_common_ancestor(const Graph &g, size_t root) {

        using Edge = typename Graph::edge_type;

        size_t N = g.n_vertices();
        size_t max_height = N - 1;
        log2_max_height = 32 - __builtin_clz(max_height);
        
        parent.assign(N, std::vector<size_t>(log2_max_height));
        depth.resize(N);

        std::function<void(int, int)> dfs = [&](int u, int p) {
            for (const Edge &e: g.edges_from(u)) {
                size_t v = e.to();
                if (v == p) {
                    continue;
                }
                parent[v][0] = u;
                depth[v] = depth[u] + 1;
                dfs(v, u);
            }
        };

        parent[root][0] = root;
        depth[root] = 0;
        dfs(root, root);

        for (size_t i = 1; i < log2_max_height; ++i) {
            for (size_t u = 0; u < N; ++u) {
                parent[u][i] = parent[parent[u][i - 1]][i - 1];
            }
        }
    }

    size_t query(size_t u, size_t v) {
        if (depth[u] > depth[v]) {
            u = n_th_parent(u, depth[u] - depth[v]);
        } else if (depth[v] > depth[u]) {
            v = n_th_parent(v, depth[v] - depth[u]);
        }
        if (u == v) {
            return u;
        }
        for (int i = log2_max_height - 1; i >= 0; --i) {
            if (parent[u][i] != parent[v][i]) {
                u = parent[u][i];
                v = parent[v][i];
            }
        }
        return parent[u][0];
    }
};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    int n;
    cin >> n;
    graph<edge> g(n);
    REP(i, n) {
        int k;
        cin >> k;
        REP(_, k) {
            int c;
            cin >> c;
            g.add_edge(i, c);
        }
    }

    int root = 0;
    lowest_common_ancestor lcm(g, root);

    int q;
    cin >> q;
    REP(_, q) {
        int u, v;
        cin >> u >> v;
        cout << lcm.query(u, v) << '\n';
    }
    cout << flush;

    return 0;
}



Measured memory_bytes: 37888