import std.stdio, std.string, std.conv, std.range;
import std.algorithm, std.array, std.typecons, std.container;
import std.math, std.numeric, std.random, core.bitop;

enum inf = 1_001_001_001;
enum infl = 1_001_001_001_001_001_001L;


struct LCA {
    int N, L, root;
    int[] depth;
    int[][] dp;

    this(int[][] adj, int root) {
        import std.conv : to;

        N = adj.length.to!int;
        while ((1 << L) <= N) L++;
        this.root = root;
        depth = new int[](N);
        dp = new int[][](N, L);
        dfs(adj, this.root, -1);

        foreach (i ; 1 .. L) {
            foreach (v ; 0 .. N) {
                if ((1 << i) > depth[v]) continue;
                dp[v][i] = dp[dp[v][i - 1]][i - 1];
            }
        }
    }

    void clear() {
        N = L = root = 0;
        depth.destroy();
        dp.destroy();
    }

    void dfs(int[][] adj, int v, int p) {
        dp[v][] = -1;
        dp[v][0] = p;
        depth[v] = (p == -1 ? 0 : depth[p] + 1);
        foreach (u ; adj[v]) if (u != p) {
            dfs(adj, u, v);
        }
    }

    int query(int u, int v) {
        import std.algorithm : swap;

        if (depth[u] > depth[v]) swap(u, v);
        // depth[u] <= depth[v]
        int dif = depth[v] - depth[u];

        // v を引き上げて u と v の深さを揃える
        foreach_reverse (i ; 0 .. L) {
            if (dif & 1 << i) {
                v = dp[v][i];
            }
        }

        if (u == v) return u;

        // u と v を lca(u, v) の一つ下まで引き上げる
        foreach_reverse (i ; 0 .. L) {
            if (dp[u][i] != dp[v][i]) {
                u = dp[u][i];
                v = dp[v][i];
            }
        }

        return dp[u][0];
    }

    alias opCall = query;

    int dist(int u, int v) {
        return depth[u] + depth[v] - 2 * depth[query(u, v)];
    }
}

unittest {
    auto adj = [[1, 2, 3],
                [0, 4, 5],
                [0, 6],
                [0, 7, 8],
                [1],
                [1, 9],
                [2],
                [3],
                [3],
                [5]];

    auto lca = LCA(adj, 0);

    assert(lca(4, 9) == 1);
    assert(lca(1, 3) == 0);
    assert(lca(1, 9) == 1);
    assert(lca(6, 6) == 6);
    assert(lca(9, 8) == 0);

    assert(lca.dist(0, 9) == 3);
    assert(lca.dist(4, 9) == 3);
    assert(lca.dist(0, 6) == 2);
    assert(lca.dist(9, 8) == 5);
    assert(lca.dist(0, 0) == 0);
}



void main() {
    int N;
    scan(N);
    auto adj = new int[][](N, 0);
    foreach (i ; 0 .. N) {
        auto ln = readln.split.to!(int[]);
        foreach (u ; ln[1 .. $]) {
            adj[i] ~= u;
            adj[u] ~= i;
        }
    }

    auto lca = LCA(adj, 0);
    
    int Q;
    scan(Q);

    foreach (_ ; 0 .. Q) {
        int u, v;
        scan(u, v);
        writeln(lca(u, v));
    }
}






void scan(T...)(ref T args) {
    auto line = readln.split;
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront;
    }
    assert(line.empty);
}

void fillAll(R, T)(ref R arr, T value) {
    static if (is(typeof(arr[] = value))) {
        arr[] = value;
    }
    else {
        foreach (ref e; arr) {
            fillAll(e, value);
        }
    }
}

bool chmin(T, U...)(ref T x, U args) {
    bool isChanged;
    foreach (arg; args) if (x > arg) {
        x = arg;
        isChanged = true;
    }
    return isChanged;
}

bool chmax(T, U...)(ref T x, U args) {
    bool isChanged;
    foreach (arg; args) if (x < arg) {
        x = arg;
        isChanged = true;
    }
    return isChanged;
}

void yes(bool ok, string y = "Yes", string n = "No") {
    return writeln(ok ? y : n);
}



Measured memory_bytes: 41336