#include <bits/stdc++.h>
using namespace std;

using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using LL = long long;
using VL = vector<LL>;
using VVL = vector<VL>;
using PLL = pair<LL, LL>;
using VS = vector<string>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))

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

#define FF first
#define SS second
template<class S, class T>
istream& operator>>(istream& is, pair<S,T>& p){
  return is >> p.FF >> p.SS;
}
template<class S, class T>
ostream& operator<<(ostream& os, const pair<S,T>& p){
  return os << p.FF << " " << p.SS;
}
template<class T>
void maxi(T& x, T y){
  if(x < y) x = y;
}
template<class T>
void mini(T& x, T y){
  if(x > y) x = y;
}


const double EPS = 1e-10;
const double PI  = acos(-1.0);
const LL MOD = 1e9+7;


struct Edge{
  int to, cost;

  Edge(int t, int c = 0): to(t), cost(c)
  {}
  bool operator>(const Edge& rhs) const{
	return cost > rhs.cost;
  }
  bool operator<(const Edge& rhs) const{
	return cost < rhs.cost;
  }

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

void add_edge(Graph& graph, int u, int v, int cost = 0){
  graph[u].push_back(Edge(v,cost));
  graph[v].push_back(Edge(u,cost));
}

struct HL{
  int N;
  VI depth;
  VI par;
  VI sz;
  //! ????????????????????????????§????
  VI xs;
  //! ?????????????±???????Heavy???id
  VI heavy_id;
  //! ?????????????????????
  VI heavy_nth;
  //! heavys[id] := {id???Heavy???????????????}
  VVI heavys;
  //! Heavy??????????????¨?????¨??¨????????¨????????????heavy_id
  VI heavy_par;
  //! heavy?????°
  int H;

  HL(const Graph& G, int root = 0, const VI& xs_ = {}){
	N = SZ(G);
	depth.assign(N, 0);
	par.assign(N, -1);
	sz.assign(N, 1);
	if(!xs_.empty())
	  xs = xs_;
	else
	  xs.assign(N, 0);
	heavy_id.assign(N, -1);
	heavy_nth.assign(N, 0);
	heavys.assign(N, {});
	heavy_par.assign(N, -1);

	function<void(int,int)> init = [&](int u, int p){
	  par[u] = p;
	  for(auto& e: G[u]){
		if(e.to == p){
		  continue;
		}
		depth[e.to] = depth[u] + 1;
		init(e.to, u);
		sz[u] += sz[e.to];
		if(xs_.empty())
		  xs[e.to] = e.cost;
	  }
	};
	depth[root] = 0;
	init(root, -1);
	H = 1;
	function<void(int,int)> calcHL = [&](int u, int p){
	  heavy_nth[u] = SZ(heavys[heavy_id[u]]);
	  heavys[heavy_id[u]].PB(u);

	  int max_u = -1;
	  for(auto& e: G[u]){
		if(e.to == p) continue;
		if(max_u < 0 || sz[max_u] < sz[e.to])
		  max_u = e.to;
	  }

	  if(max_u < 0) return;
	  heavy_id[max_u] = heavy_id[u];
	  calcHL(max_u, u);
	  
	  for(auto& e: G[u]){
		if(e.to == p || e.to == max_u) continue;
		heavy_id[e.to] = H++;
		calcHL(e.to, u);
		heavy_par[heavy_id[e.to]] = heavy_id[u];
	  }
	};
	heavy_id[root] = 0;
	calcHL(root, -1);
  }

  int LCA(int u, int v){
	while(true){
	  if(heavy_id[u] == heavy_id[v])
		return (depth[u] <= depth[v]? u: v);

	  int ru = heavys[heavy_id[u]][0];
	  int rv = heavys[heavy_id[v]][0];
	  if(depth[ru] < depth[rv])
		v = par[rv];
	  else
		u = par[ru];
	}
  }
};

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

  int N;
  cin >> N;
  Graph G(N);
  REP(i,N){
	int k;
	cin >> k;
	REP(j,k){
	  int c;
	  cin >> c;
	  add_edge(G, i, c);
	}
  }

  HL hl(G);  
  int Q;
  cin >> Q;
  while(Q--){
	int u, v;
	cin >> u >> v;
	cout << hl.LCA(u, v) << endl;
  }

  return 0;
}

Measured memory_bytes: 21836