// Original C++ solution (slower):
#include <iostream>

#include <vector>

#include <map>

#include <string.h>

#include <algorithm>

#define P pair<int,int>

#define INF (1<<30)

using namespace std;



vector<int> Ind(100010);		//Ind[n]  ??\???n???euler tour??¨??§???????????°?????????

vector<bool> f(100010, false);	//

vector<vector<int>> T(100010);	//??°??????

vector<P> ET;                   //????????¢?´¢??¨



void dfs(int n,int dep) {

	f[n] = true;

	ET.emplace_back(make_pair(dep,n));

	Ind[n] = ET.size() - 1;

	for (int next : T[n]) {

		if (f[next] == true) continue;

		dfs(next,dep + 1);

		ET.emplace_back(make_pair(dep,n));

	}

}



P RMQ(int a, int b, int k, int l, int r, vector<P>& node) {

	if (r <= a || b <= l) {return P(INF, INF); }

	if (a <= l && r <= b) return node[k];



	P vl = RMQ(a, b, 2 * k + 1, l, (l + r) / 2,node);

	P vr = RMQ(a, b, 2 * k + 2, (l + r) / 2, r, node);

	return min(vl, vr);

}



int main() {

	cin.tie(0); ios::sync_with_stdio(false);

	//Graph initialize

	int n_; cin >> n_;

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

		int k; cin >> k;

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

			int c; cin >> c;

			T[i].emplace_back(c);

			T[c].emplace_back(i);

		}

	}

	//ET??¨?????????

	dfs(0,0);



	//RMQ initialize

	n_ = ET.size();



	int n = 1;

	while (n < n_) n *= 2;

	vector<P> node(2 * n - 1, P(INF, INF));



	for (int i = 0; i < n_;i++) { node[n - 1 + i] = ET[i]; }

	for (int i = n - 2; i >= 0; i--) { node[i] = min(node[2 * i + 1], node[2 * i + 2]); }



	//Answer

	int q; cin >> q;

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

		int u, v; cin >> u >> v;

		int a = Ind[u], b = Ind[v];

		if (a > b) { swap(a, b); }

		if (a == b) { cout << u << endl; continue; }

		cout << RMQ(a,b, 0, 0, n, node).second << endl;

	}

}

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

using namespace std;

typedef long long ll;

typedef pair<int, int> pii;

typedef pair<ll, ll> pll;

const int INF = 1e9;

const ll LINF = 1e18;

template<class S,class T> ostream& operator << (ostream& out,const pair<S,T>& o){ out << "(" << o.first << "," << o.second << ")"; return out; }

template<class T> ostream& operator << (ostream& out,const vector<T> V){ for(int i = 0; i < V.size(); i++){ out << V[i]; if(i!=V.size()-1) out << " ";} return out; }

template<class T> ostream& operator << (ostream& out,const vector<vector<T> > Mat){ for(int i = 0; i < Mat.size(); i++) { if(i != 0) out << endl; out << Mat[i];} return out; }

template<class S,class T> ostream& operator << (ostream& out,const map<S,T> mp){ out << "{ "; for(auto it = mp.begin(); it != mp.end(); it++){ out << it->first << ":" << it->second; if(mp.size()-1 != distance(mp.begin(),it)) out << ", "; } out << " }"; return out; }





// HL-Decomposition

struct HLD{

    typedef ll TYPE;

    typedef pair<TYPE,TYPE> PTT;

    TYPE V; // 頂点数

    TYPE root;

    vector<vector<TYPE>> G;

    vector<TYPE> parent,Hchild,number,id,group,depth;

    vector<PTT> paths; // [u,v]間の経路を分解(最大でもlogN)

    vector<PTT> Ledges; // pathsを結ぶライドエッジ

    

    HLD() {root = V = -1; }

    HLD(TYPE V):

    V(V),root(0),G(V),parent(V,-1),Hchild(V,-1),number(V,-1),id(V,-1),group(V,-1),depth(V,0){}

    void init(TYPE V){

        V = V; root = 0;

        G.clear(); parent.clear(); Hchild.clear(); number.clear();

        id.clear(); group.clear(); depth.clear();

        G.resize(V); parent.assign(V,-1); Hchild.assign(V,-1);

        number.assign(V,-1); id.assign(V,-1); group.assign(V,-1); depth.assign(V,0);

    }

    

    void add_edge(TYPE u,TYPE v){ G[u].push_back(v); G[v].push_back(u);}

    void build(TYPE _root = 0){

        root = _root;

        int num = 0;

        dfs1(); init_number(num); dfs2();

    }

    TYPE dfs1(TYPE pos = -1,TYPE pre = -1){

        if(pos == -1) pos = root;

        TYPE maxw = -1, weight = 1;

        for(TYPE next:G[pos]){

            if(next == pre) continue;

            TYPE child_weight = dfs1(next,pos);

            weight += child_weight;

            if(maxw < child_weight){ Hchild[pos] = next; maxw = child_weight; }

        }

        return weight;

    }

    void dfs2(TYPE pos = -1,TYPE pre = -1,TYPE dep = 0,TYPE g = -1){

        if(pos == -1) pos = g = root;

        parent[pos] = pre; depth[pos] = dep; group[pos] = g;

        for(TYPE next:G[pos]){

            if(next == pre) continue;

            dfs2(next,pos,dep+1,Hchild[pos]==next?g:next);

        }

    }

    void init_number(int& num,TYPE pos = -1,TYPE pre = -1){

        if(pos == -1) pos = root;

        number[pos] = num++;

        id[number[pos]] = pos;

        if(Hchild[pos] >= 0) init_number(num,Hchild[pos],pos);

        for(TYPE next:G[pos]){

            if(next != pre && next != Hchild[pos]) init_number(num,next,pos);

        }

    }

    

    void buildPaths(TYPE u,TYPE v){

        if(depth[group[u]] < depth[group[v]]) swap(u,v);

        TYPE num_u=number[u], num_v=number[v];

        if(same(u,v)){ paths.push_back({min(num_u,num_v),max(num_u,num_v)}); return;}

        TYPE group_u = group[u];

        buildPaths(parent[group_u],v);

        paths.push_back({number[group_u], number[u]});

        Ledges.push_back({number[parent[group_u]], number[group_u]});

    }

    

    TYPE lca(TYPE u,TYPE v){

        if(depth[group[u]] < depth[group[v]]) swap(u,v);

        if(same(u,v)) return depth[u] < depth[v]?u:v;

        return lca(parent[group[u]],v);

    }

    pair<vector<PTT>,vector<PTT>> getPath(TYPE u,TYPE v){

        paths.clear(); Ledges.clear();

        buildPaths(u,v);

        return make_pair(paths,Ledges);

    }

    bool same(TYPE a,TYPE b){return group[a] == group[b];}

};



// ================================= //

// use example



/*

 update : [s,t)にxを加算する

 query : [s,t) の総和を出力する

 */

const ll INIT = 0;

struct SegTree {

    int N;

    ll init_v;

    vector<ll> node, lazy;

    SegTree(int _N):init_v(INIT) {

        N = 1; while (N < _N) N *= 2;

        node.resize(2 * N - 1, init_v); lazy.resize(2 * N - 1, init_v);

    }

    

    void lazy_evaluate(int k) {

        node[k] += lazy[k]; // add のため加算

        if (k < N - 1) { lazy[2 * k + 1] += lazy[k] / 2; lazy[2 * k + 2] += lazy[k] / 2; }

        lazy[k] = 0;

    }

    

    /* [a,b) 引数の範囲に注意!! s~tまでを更新→update(s,t+1,~) */

    ll update(int a, int b, int x) { return update(a, b, 0, 0, N, x); }

    ll update(int a, int b, int k, int l, int r, int x) {

        if (r <= a || b <= l) { lazy_evaluate(k); return node[k]; }

        if (a <= l && r <= b) { lazy[k] += (r - l) * x; lazy_evaluate(k); return node[k]; }

        else {

            lazy_evaluate(k);

            ll vl = update(a, b, 2 * k + 1, l, (l + r) / 2, x);

            ll vr = update(a, b, 2 * k + 2, (l + r) / 2, r, x);

            return node[k] = vl + vr;

        }

    }

    

    /* [a,b) 引数の範囲に注意!! */

    ll query(int a, int b) { return query(a, b, 0, 0, N); }

    ll query(int a, int b, int k, int l, int r) {

        if (r <= a || b <= l) return init_v;

        if (a <= l && r <= b) { lazy_evaluate(k); return node[k]; }

        else {

            lazy_evaluate(k);

            ll vl = query(a, b, 2 * k + 1, l, (l + r) / 2);

            ll vr = query(a, b, 2 * k + 2, (l + r) / 2, r);

            return vl + vr;

        }

    }

};





// LCA : http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_5_C&lang=jp

void GRL_5_C(){

    ll n; cin >> n;

    HLD hld(n);

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

        ll k; cin >> k;

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

            ll c; cin >> c;

            hld.add_edge(i, c);

        }

    }

    hld.build();

    ll q; cin >> q;

    while(q--){

        ll u,v; cin >> u >> v;

        cout << hld.lca(u,v) << endl;

    }

}

int main(void) {

    cin.tie(0); ios_base::sync_with_stdio(false);

    GRL_5_C();

    return 0;

}




// Fastest known solution for this problem: