// Slower C++ solution:
#include <iostream>

#include <vector>

#include <algorithm>

#define all(c) (c).begin(),(c).end()



#define maxv 100000



using namespace std;



int n,len;

vector<int> tree[maxv], in, out, up[100];



void dfs(int u, int p, int &k){

  in[u] = k++;

  up[0][u] = p;

  for(int i = 1; i < len; i++)

    up[i][u] = up[i - 1][up[i - 1][u]];



  for(int i = 0; i < tree[u].size(); i++){

    if(tree[u][i] != p)dfs(tree[u][i],u,k);

  }

  out[u] = k++;

}



void init(int root){

  len = 1;

  while((1 << len) <= n)len++;

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

    up[i].resize(n);

    fill(all(up[i]),0);

  }

  in.resize(n);

  out.resize(n);

  fill(all(in),0);

  fill(all(out),0);

  int k=0;

  dfs(root,root,k);

}



bool isParent(int parent, int child){

  return in[parent] <= in[child] && out[child] <= out[parent];

}



int lca(int a, int b){

  if(isParent(a,b))return a;

  if(isParent(b,a))return b;

  for(int i = len - 1; i >= 0; i--){

    if(!isParent(up[i][a],b))a = up[i][a];

  }

  return up[0][a];

}





int main(void){



  cin >> n;

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

    int k,c;

    cin >> k;

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

      cin >> c;

      tree[i].push_back(c);

    }

  }



  init(0);



  int q;

  cin >> q;

  while(q--){

    int u,v;

    cin >> u >> v;

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

  }

  return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.4826768970835027x):
#include<bits/stdc++.h>



#define INF (1<<29)

#define max_n 10000



using namespace std;



struct node_t;



struct edge{

  node_t *u,*v;

  int val,mini;

  edge(node_t *u, node_t *v, int val):u(u),v(v),val(val),mini(val){}

  inline node_t *opposite(node_t *from){return (from==u)?u:v;}

};



struct node_t{

  node_t *pp,*lp,*rp;

  edge *pe,*le,*re;

  int id,val,mini,minId,lazy;

  bool rev;



  node_t(int id,int v):id(id),val(v),mini(v){

    pp=lp=rp=NULL;

    rev=false; 

    lazy=0; 

    update();

  }

   

  void update(){

    mini=val,minId=id;

    //pp=pe->opposite(this);

    //lp=le->opposite(this);

    //rp=re->opposite(this);

    push();

    if(lp)lp->push();

    if(rp)rp->push();

    if(lp && mini>lp->mini)mini=lp->mini,minId=lp->minId;

    if(rp && mini>rp->mini)mini=rp->mini,minId=rp->minId;

  }

   

  void push(){

    if(rev){

      rev=false;

      swap(lp,rp);

      swap(le,re);

      //lp=le->opposite(this);

      //rp=re->opposite(this);

      

      if(lp)lp->rev^=true;

      if(rp)rp->rev^=true;

    }

    if(lp)lp->lazy+=lazy;

    if(rp)rp->lazy+=lazy;



    val+=lazy,mini+=lazy,lazy=0;

  }

 

  bool is_root(){

    return !pp || (pp->lp != this && pp->rp != this);

  }

  

  void rotr(){

    node_t *q=pp,*r=q->pp;

    if((q->lp=rp))rp->pp=q;

    rp=q;q->pp=this;

    if((pp=r)){

      if(r->lp==q)r->lp=this;

      if(r->rp==q)r->rp=this;

    }

    q->update();

  }



  void rotl(){

    node_t *q=pp,*r=q->pp;

    if((q->rp=lp))lp->pp=q;

    lp=q;q->pp=this;

    if((pp=r)){

      if(r->lp==q)r->lp=this;

      if(r->rp==q)r->rp=this;

    }

    q->update();

  }



  void splay(){

    while(!is_root()){

      node_t *q=pp;

      node_t *r=q->pp;

      if(!q->is_root())r->push();

      q->push();

      push();

      if(q->is_root()){

	if(q->lp==this)rotr();

	else rotl();

      } else {

	if(r->lp==q){

	  if(q->lp==this){q->rotr();rotr();}

	  else {rotl();rotr();}

	} else {

	  if(q->rp==this){q->rotl();rotl();}

	  else {rotr();rotl();}

	}

      }

    }

    push();

    update();

  }

};



node_t *expose(node_t *x){

  node_t *rp=NULL;

  for(node_t *p=x;p;p=p->pp){

    p->splay();

    p->rp=rp;

    rp=p;

  }

  x->splay();

  return rp;

}



node_t *find_root(node_t *x){

  expose(x);

  while(x->lp)x=x->lp;

  return x;

}



bool isConnected(node_t *x, node_t *y){

  if(x->id==y->id)return true;

  expose(x);

  //assert(x->pp==NULL);

  expose(y);

  return (x->pp != NULL);

}



//Verified.

void evert(node_t *p){

  expose(p);

  p->rev^=true;

}



void cut(node_t *c){

  expose(c);

  node_t *p=c->lp;

  c->lp=NULL;

  p->pp=NULL;

}



void link(node_t *c,node_t *p){

  if(isConnected(c,p))return;

  evert(c);

  c->pp=p;

}



//Verified.

int minId(node_t *x){expose(x); return x->minId;}

void add(node_t *x,int val){ expose(x); x->lazy=val; }



//Verified. AOJ GRL_5_C

node_t *lca(node_t *x,node_t* y){

  expose(x);

  return expose(y);

}



//Verified.

int min(node_t *from, node_t *to){

  evert(from);

  expose(to);

  return to->mini;

}



//Verified.

void add(node_t *from, node_t *to,int v){

  evert(from);

  expose(to);

  to->lazy+=v;

}





//AOJ GRL_5_C

node_t *node[100001];



int main(void){

  int n;

  cin >> n;

  

  for(int i=0;i<n;i++)node[i]=new node_t(i,0);

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

    int k,t;

    cin >> k;

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

      cin >> t;

      link(node[t],node[i]);

    }

  }



  int q;

  cin >> q;

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

    int u,v;

    cin >> u >> v;

    cout << lca(node[u],node[v])->id << endl;

  }

  

  return 0;

}