#include <iostream>
#include <vector>
#include <cmath>

using namespace std;
constexpr int MAX_LOG_V = 50;
template<class T> inline bool chmax(T &a, T b){ if(a < b){a = b; return true;} return false;}

struct Edge{
    int to,weight;
    Edge(int t,int w) : to(t), weight(w){}
};

using Edges = vector<Edge>;
using Graph = vector<Edges>;

class Tree{
    public:
        Tree(int size) : mGraph(size), mMemo(size) {}
        void add_edge(int s, int t, int w = 1){
            mGraph[s].emplace_back(t,w);
            mGraph[t].emplace_back(s,w);
        }

        // diameter of a tree
        pair<int,int> dfs(int v, int pv){
            pair<int,int> ret(0,v);
            for(Edge nv : mGraph[v]){
                if(nv.to == pv) continue;
                pair<int,int> tmp = dfs(nv.to,v);
                if(chmax(ret.first,tmp.first + nv.weight)){
                    ret.second = tmp.second;
                }
            }
            return ret;
        }

        int diameter(){
            pair<int,int> s = dfs(0,-1);
            pair<int,int> t = dfs(s.second,-1);
            return t.first;
        }
        //

        // height of a tree
        int dfs_memo(int v,int e){
            if(mMemo[v][e].weight >= 0) return mMemo[v][e].weight;
            mMemo[v][e].weight = mGraph[v][e].weight;
            int nv = mMemo[v][e].to;
            for(int ne = 0; ne < mMemo[nv].size(); ++ne){
                if(mMemo[nv][ne].to == v) continue;
                mMemo[v][e].weight = max(mMemo[v][e].weight, dfs_memo(nv,ne) + mGraph[v][e].weight);
            }
            return mMemo[v][e].weight;
        }

        vector<int> height(){
            mMemo = mGraph;
            // init memo
            for(int i = 0; i < mMemo.size(); ++i){
                for(int j = 0; j < mMemo[i].size(); ++j){
                    mMemo[i][j].weight = -1;
                }
            }
            //
            for(int i = 0; i < mMemo.size(); ++i){
                for(int j = 0; j < mMemo[i].size(); ++j){
                    if(mMemo[i][j].weight < 0){
                        mMemo[i][j].weight = dfs_memo(i,j);
                    }
                }
            }

           // calc result
           vector<int> ret(mMemo.size());
           for(int i = 0; i < mMemo.size(); ++i){
               for(int j = 0; j < mMemo[i].size(); ++j){
                   ret[i] = max(ret[i],mMemo[i][j].weight);
               }
           }
           return ret;
        }
        //
        
        // Lowest Common Ancester
        void SetParentAndDepth(int v,int pv, int d){
            mPar[0][v] = pv; // v is pv's 2^0 parent
            mDepth[v] = d;
            for(auto nv : mGraph[v]){
                if(nv.to == pv) continue;
                SetParentAndDepth(nv.to,v,d+1);
            }
        }

        void Init(int root){
            mPar.resize(MAX_LOG_V,vector<int>(mGraph.size()));
            mDepth.resize(mGraph.size());
            SetParentAndDepth(root,-1,0);
            // calc 2^k parent of each vert
            for(int k = 0; k + 1 < MAX_LOG_V; ++k){
                for(int v = 0; v < mGraph.size(); ++v){
                    if(mPar[k][v] < 0) mPar[k+1][v] = -1; // not having parent
                    else mPar[k+1][v] = mPar[k][mPar[k][v]];
                }
            }
        }

        int GetLca(int u,int v){
            while(mDepth[u] > mDepth[v]) swap(u,v);
            for(int k = 0; k < MAX_LOG_V; ++k){
                if((mDepth[v] - mDepth[u]) >> k & 1){
                    v = mPar[k][v];
                }
            }
            if(u==v) return u;
            for(int k = MAX_LOG_V - 1; k >= 0; --k){
                if(mPar[k][u] != mPar[k][v]) {
                    u = mPar[k][u];
                    v = mPar[k][v];
                }
            }
            return mPar[0][u];
        }
        //


    private:
        Graph mGraph;
        Graph mMemo;
        
        // LCA
        vector<vector<int> > mPar;
        vector<int> mDepth;
};

int main(){
    int n,q,k,x,y;
    cin >> n;
    Tree tree(n);
    for(int i = 0; i < n; ++i){
        cin >> k;
        for(int j = 0; j < k; ++j){
            cin >> x;
            tree.add_edge(i,x);
        }
    }
    tree.Init(0);
    cin >> q;
    for(int i = 0; i < q; ++i){
        cin >> x >> y;
        cout << tree.GetLca(x,y) << '\n';
    }
    return 0;
}


Measured memory_bytes: 33472