#[allow(unused_imports)]
use std::io::{stdin, Read, StdinLock};
#[allow(unused_imports)]
use std::cmp::{max, min, Ordering};
#[allow(unused_imports)]
use std::str::FromStr;
#[allow(unused_imports)]
use std::collections::{HashSet, HashMap, BinaryHeap};
#[allow(unused_imports)]
use std::vec::Vec;

#[allow(dead_code)]
const INF: i32 = 1000_000_000;
#[allow(dead_code)]
const INFLL: i64 = 1000_000_000_000_000_000;
#[allow(dead_code)]
const EPS: f64 = 1.0e-10;
#[allow(dead_code)]
const MOD: i32 = 1000_000_007;

struct Scanner<'a> {
    cin: StdinLock<'a>,
}

impl<'a> Scanner<'a> {
    #[allow(dead_code)]
    fn new(cin: StdinLock<'a>) -> Scanner<'a> {
        Scanner {cin: cin}
    }

    #[allow(dead_code)]
    fn read1<T: FromStr>(&mut self) -> Option<T> {
        let token = self.cin.by_ref().bytes().map(|c| c.unwrap() as char)
                    .skip_while(|c| c.is_whitespace())
                    .take_while(|c| !c.is_whitespace())
                    .collect::<String>();
        token.parse::<T>().ok()
    }

    #[allow(dead_code)]
    fn read<T: FromStr>(&mut self) -> T {
        self.read1().unwrap()
    }
}

trait Edge {
    fn from(&self) -> usize;
    fn to(&self) -> usize;
}

#[allow(dead_code)]
#[derive(Eq, PartialEq, PartialOrd, Clone)]
struct WeightedEdge {
    from: usize,
    to: usize,
    weight: i32,
}

impl Edge for WeightedEdge {
    fn from(&self) -> usize {
        self.from
    }
    fn to(&self) -> usize {
        self.to
    }
}

#[allow(dead_code)]
impl WeightedEdge {
    fn new(from: usize, to: usize, weight: i32) -> WeightedEdge {
        WeightedEdge {
            from: from,
            to: to,
            weight: weight
        }
    }
}

impl Ord for WeightedEdge {
    fn cmp(&self, other: &WeightedEdge) -> Ordering {
        if self.weight > other.weight {
            Ordering::Greater
        } else if self.weight < other.weight {
            Ordering::Less
        } else {
            Ordering::Equal
        }
    }
}

///
///
///
trait Graph<E: Edge> {
    fn edges(&self, v: usize) -> &std::vec::Vec<E>;
    fn node_size(&self) -> usize;
}

#[derive(Clone)]
struct WeightedGraph {
    adj_list: std::vec::Vec<std::vec::Vec<WeightedEdge>>,
}

#[allow(dead_code)]
impl WeightedGraph {
    fn new(n: usize) -> WeightedGraph {
        WeightedGraph {
            adj_list: vec![std::vec::Vec::<WeightedEdge>::new(); n],
        }
    }

    fn add_edge(&mut self, from: usize, to: usize, w: i32) {
        self.adj_list[from].push(WeightedEdge::new(from, to, w));
    }
}

impl Graph<WeightedEdge> for WeightedGraph {
    fn edges(&self, v: usize) -> &std::vec::Vec<WeightedEdge> {
        &self.adj_list[v]
    }

    fn node_size(&self) -> usize {
        self.adj_list.len()
    }
}

struct LowestCommonAncestor{
    //n: usize,
    log_n: usize,
    parent: Vec<Vec<Option<usize>>>,
    depth: Vec<usize>,
}

#[allow(dead_code)]
impl LowestCommonAncestor {
    fn new<E: Edge, G: Graph<E>>(t: &G, root: usize) -> LowestCommonAncestor {
        let mut n = t.node_size();
        let mut log_n: usize = 0;
        while n > 0 {
            log_n += 1;
            n >>= 1;
        }
        let log_n = log_n;
        let n = t.node_size();

        fn dfs<E: Edge>(t: &Graph<E>, v: usize, p: Option<usize>, d: usize, parent: &mut Vec<Vec<Option<usize>>>, depth: &mut Vec<usize>) {
            parent[0][v] = p;
            depth[v] = d;
            for e in t.edges(v) {
                if p.is_none() || e.to() != p.unwrap() {
                    dfs(t, e.to(), Some(v), d + 1, parent, depth);
                }
            }
        }

        let mut parent: Vec<Vec<Option<usize>>> = vec![vec![None; n]; log_n];
        let mut depth: Vec<usize> = vec![0; n];
        dfs(t, root, None, 0, &mut parent, &mut depth);
        for k in 0..log_n-1 {
            for v in 0..n {
                match parent[k][v] {
                    Some(p) => parent[k + 1][v] = parent[k][p],
                    None    => parent[k + 1][v] = None,
                }
            }
        }

        LowestCommonAncestor {
            //n: n,
            log_n: log_n,
            parent: parent,
            depth: depth
        }
    }

    fn depth(&self, v: usize) -> usize {
        self.depth[v]
    }

    fn dist(&self, u: usize, v: usize) -> usize {
        self.depth[u] + self.depth[v] - 2 * self.depth[self.query(u, v)]
    }

    fn parent(&self, u: usize, k: usize) -> Option<usize> {
        let mut res: Option<usize> = Some(u);
        for i in 0..self.log_n {
            if k & (1 << i) > 0 {
                match self.parent[i][res.unwrap()] {
                    Some(p) => res = Some(p),
                    None    => {
                        res = None;
                        break;
                    }
                }
            }
        }
        res
    }

    fn query(&self, u: usize, v: usize) -> usize {
        let (mut u, mut v) = if self.depth(u) > self.depth(v) { (v, u) } else { (u, v) };
        for k in 0..self.log_n {
            if (self.depth(v) - self.depth(u)) >> k & 1 > 0 {
                v = self.parent[k][v].unwrap();
            }
        }
        let res: usize;
        if u == v {
            res = u;
        } else {
            for k in (0..self.log_n).rev() {
                if self.parent[k][u] != self.parent[k][v] {
                    u = self.parent[k][u].unwrap();
                    v = self.parent[k][v].unwrap();
                }
            }
            res = self.parent[0][u].unwrap();
        }

        res
    }
}

fn main() {
    let cin = stdin();
    let cin = cin.lock();
    let mut sc = Scanner::new(cin);

    let n: usize = sc.read();
    let mut t = WeightedGraph::new(n);
    for i in 0..n {
        let k: usize = sc.read();
        for _j in 0..k {
            let c: usize = sc.read();
            t.add_edge(i, c, 0);
        }
    }
    let lca = LowestCommonAncestor::new(&t, 0);
    let q: usize = sc.read();
    for _i in 0..q {
        let u: usize = sc.read();
        let v: usize = sc.read();
        println!("{}", lca.query(u, v));
    }
}


Measured memory_bytes: 63548