Problem:
LCA: Lowest Common Ancestor For a rooted tree, find the lowest common ancestor of two nodes u and v . The given tree consists of n nodes and every node has a unique ID from 0 to n -1 where 0 is the root. Input  n  k 0  c 1  c 2 ... c k 0  k 1  c 1  c 2 ... c k 1 : k n-1  c 1  c 2 ... c k n-1  q  u 1  v 1  u 2  v 2 : u q  v q  The first line of the input includes an integer n , the number of nodes of the tree. In the next n lines, the information of node i is given. k i is the number of children of node i , and c 1 , ... c k i are node IDs of 1st, ... k th child of node i . In the next line, the number of queryies q is given. In the next q lines, pairs of u and v are given as the queries. Output For each query, print the LCA of u and v in a line. Constraints   1 ≤ n ≤ 100000    1 ≤ q ≤ 100000   Sample Input 1 8
3 1 2 3
2 4 5
0
0
0
2 6 7
0
0
4
4 6
4 7
4 3
5 2 Sample Output 1 1
1
0
0

Solution (Python):




class UnionFind:
    def __init__(self, n):
        self.nodes = [i for i in range(n)]
        self.sizes = [1 for _ in range(n)]

    def union(self, p, q):
        rp = self.root(p)
        rq = self.root(q)
        if self.sizes[rp] > self.sizes[rq]:
            self.nodes[rq] = rp
            self.sizes[rp] += self.sizes[rq]
        else:
            self.nodes[rp] = rq
            self.sizes[rq] += self.sizes[rp]

    def connected(self, p, q):
        return self.root(p) == self.root(q)

    def root(self, p):
        while p != self.nodes[p]:
            self.nodes[p] = self.nodes[self.nodes[p]]
            p = self.nodes[p]

        return p


class Edge:
    __slots__ = ('v', 'w')

    def __init__(self, v, w):
        self.v = v
        self.w = w

    def either(self):
        return self.v

    def other(self, v):
        if v == self.v:
            return self.w
        else:
            return self.v


class WeightedEdge(Edge):
    __slots__ = ('v', 'w', 'weight')

    def __init__(self, v, w, weight):
        super().__init__(v, w)
        self.weight = weight


class Graph:
    def __init__(self, v):
        self.v = v
        self._edges = [[] for _ in range(v)]

    def add(self, e):
        self._edges[e.v].append(e)
        self._edges[e.w].append(e)

    def adj(self, v):
        return self._edges[v]

    def edges(self):
        for es in self._edges:
            for e in es:
                yield e


def lca(graph, root, queries):
    index = [set() for _ in range(graph.v)]
    for v, w in queries:
        index[v].add((v, w))

    visited = [False] * graph.v
    stored = [False] * graph.v
    parents = [None] * graph.v
    uf = UnionFind(graph.v)
    res = {}
    stack = [root]
    while stack:
        v = stack.pop()
        if not visited[v]:
            visited[v] = True
            stack.append(v)
            for e in graph.adj(v):
                w = e.other(v)
                if not visited[w]:
                    stack.append(w)
                    parents[w] = v
        else:
            stored[v] = True
            p = parents[v]
            rest = set()
            for i, j in index[v]:
                if stored[i] and stored[j]:
                    if uf.connected(i, j) and (i, j) not in res:
                        res[(i, j)] = v
                    else:
                        rest.add((i, j))
                else:
                    index[j].add((i, j))
            index[v] = None
            if p is not None:
                uf.union(p, v)
                index[p].update(rest)

    return res


def run():
    n = int(input())
    g = Graph(n)

    for i in range(n):
        k, *cs = [int(i) for i in input().split()]
        if k > 0:
            for j in cs:
                g.add(Edge(i, j))

    q = int(input())
    qs = []
    for _ in range(q):
        v, w = [int(i) for i in input().split()]
        qs.append((v, w))

    res = lca(g, 0, qs)
    for v, w in qs:
        print(res[(v, w)])


if __name__ == '__main__':
    run()

Solution (Python):
class Lca:
    def __init__(self, E, root):
        import sys
        sys.setrecursionlimit(500000)
        self.root = root
        self.E = E  
        self.n = len(E)  
        self.logn = 1  
        while self.n >= (1<<self.logn):
            self.logn += 1

        
        self.parent = [[-1]*self.n for _ in range(self.logn)]

        self.depth = [0] * self.n
        self.dfs(root, -1, 0)
        for k in range(self.logn-1):
            for v in range(self.n):
                p_ = self.parent[k][v]
                if p_ >= 0:
                    self.parent[k+1][v] = self.parent[k][p_]

    def dfs(self, v, p, dep):
        
        self.parent[0][v] = p
        self.depth[v] = dep
        for e in self.E[v]:
            if e != p:
                self.dfs(e, v, dep+1)

    def get(self, u, v):
        if self.depth[u] > self.depth[v]:
            u, v = v, u  
        dep_diff = self.depth[v]-self.depth[u]
        for k in range(self.logn):
            if dep_diff >> k & 1:
                v = self.parent[k][v]
        if u==v:
            return u
        for k in range(self.logn-1, -1, -1):
            if self.parent[k][u] != self.parent[k][v]:
                u = self.parent[k][u]
                v = self.parent[k][v]
        return self.parent[0][u]

n = int(input())
E = [[] for _ in range(n)]
for i in range(n):
    kc = list(map(int, input().split()))
    k = kc[0]
    for c in kc[1:]:
        E[i].append(c)
        E[c].append(i)
lca = Lca(E, 0)
Q = int(input())
for _ in range(Q):
    u, v = map(int, input().split())
    print(lca.get(u, v))

Solution (Python):
from sys import stdin
from collections import defaultdict
readline = stdin.readline
 
 
def main():
    n = int(readline())
    g = dict()
    for i in range(n):
        nodes = list(map(int, readline().split()))
        g[i] = nodes[1:]
    
    euler, height = euler_tour(g, n)
    index = defaultdict(list)
    for i in range(len(euler)):
        index[euler[i]].append(i)
    rmql = [(height[i], i) for i in euler]
    rmq = segment_tree(rmql,min,(float('inf'),))
 
    q = int(readline())
    for i in range(q):
        u, v = map(int, readline().split())
        l, r = index[u][0], index[v][-1]
        if l > r:
            l, r = index[v][0], index[u][-1]
        print(rmq.find(l, r)[1])
 
 
def euler_tour(g, size):
    height = [None] * size
    euler = []
    root = 0
    dfs_stack = [(root, None, 0)]
    while dfs_stack:
        u, prev, h = dfs_stack.pop()
        height[u] = h
        euler.append(prev)
        if g[u]:
            dfs_stack.extend((v, u, h + 1) for v in g[u])
        else:
            euler.append(u)
    return euler[1:], height
     
import math
class segment_tree:
    def __init__(self, dat, query, default=0):
        self.offset = 2 ** math.ceil(math.log(len(dat), 2))
        self.table = [default] * self.offset + dat + [default] * (self.offset - len(dat))
        self.query = query
        for i in reversed(range(1, self.offset)):
            self.table[i] = self.query(self.table[2 * i], self.table[2 * i + 1])
 
    
    def find(self, l, r):
        return self.query(self.__range(l,r))
 
    def __range(self, l, r):
        l += self.offset
        r += self.offset
        while l <= r:
            if l & 1:
                yield self.table[l]
                l += 1
            l >>= 1
            if r & 1 == 0:
                yield self.table[r]
                r -= 1
            r >>= 1
         
    def update(self, i, x):
        i += self.offset
        self.table[i] = x
        while 1 < i:
            i >>= 1
            self.table[i] = self.query(self.table[2 * i], self.table[2 * i + 1])
main()

Solution (Python):
class Edge:
    def __init__(self, dst, weight):
        self.dst, self.weight = dst, weight

    def __lt__(self, e):
        return self.weight > e.weight


class Graph:
    def __init__(self, V):
        self.V = V
        self.E = [[] for _ in range(V)]

    def add_edge(self, src, dst, weight):
        self.E[src].append(Edge(dst, weight))


class HeavyLightDecomposition:
    def __init__(self, g, root=0):
        self.g = g
        self.vid, self.head, self.heavy, self.parent = [0] * g.V, [-1] * g.V, [-1] * g.V, [-1] * g.V
        self.dfs(root)
        self.bfs(root)

    def dfs(self, root):
        stack = [(root, -1)]
        sub, max_sub = [1] * self.g.V, [(0, -1)] * self.g.V
        used = [False] * self.g.V

        while stack:
            v, par = stack.pop()
            if not used[v]:
                used[v] = True
                self.parent[v] = par
                stack.append((v, par))
                stack.extend((e.dst, v) for e in self.g.E[v] if e.dst != par)
            else:
                if par != -1:
                    sub[par] += sub[v]
                    max_sub[par] = max(max_sub[par], (sub[v], v))
                self.heavy[v] = max_sub[v][1]

    def bfs(self, root=0):
        from collections import deque
        k, que = 0, deque([root])
        while que:
            r = v = que.popleft()
            while v != -1:
                self.vid[v], self.head[v] = k, r
                for e in self.g.E[v]:
                    if e.dst != self.parent[v] and e.dst != self.heavy[v]:
                        que.append(e.dst)
                k += 1
                v = self.heavy[v]

    def lca(self, u, v):
        while self.head[u] != self.head[v]:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
            v = self.parent[self.head[v]]
        else:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
        return u

N = int(input())
g = Graph(N)
for i in range(N):
    for c in map(int, input().split()[1:]):
        g.add_edge(i, c, 1)
        g.add_edge(c, i, 1)
hld = HeavyLightDecomposition(g)
Q = int(input())
for _ in range(Q):
    u, v = map(int, input().split())
    print(hld.lca(u, v))

Solution (Python):
class HeavyLightDecomposition:
    def __init__(self, g, root=0):
        self.g = g
        self.vid, self.head, self.heavy, self.parent = [0] * len(g), [-1] * len(g), [-1] * len(g), [-1] * len(g)
        self.dfs(root)
        self.bfs(root)

    def dfs(self, root):
        stack = [(root, -1)]
        sub, max_sub = [1] * len(self.g), [(0, -1)] * len(self.g)
        used = [False] * len(self.g)

        while stack:
            v, par = stack.pop()
            if not used[v]:
                used[v] = True
                self.parent[v] = par
                stack.append((v, par))
                stack.extend((c, v) for c in self.g[v] if c != par)
            else:
                if par != -1:
                    sub[par] += sub[v]
                    max_sub[par] = max(max_sub[par], (sub[v], v))
                self.heavy[v] = max_sub[v][1]

    def bfs(self, root=0):
        from collections import deque
        k, que = 0, deque([root])
        while que:
            r = v = que.popleft()
            while v != -1:
                self.vid[v], self.head[v] = k, r
                for c in self.g[v]:
                    if c != self.parent[v] and c != self.heavy[v]:
                        que.append(c)
                k += 1
                v = self.heavy[v]

    def lca(self, u, v):
        while self.head[u] != self.head[v]:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
            v = self.parent[self.head[v]]
        else:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
        return u

N = int(input())
g = [[] for _ in range(N)]
for i in range(N):
    for c in map(int, input().split()[1:]):
        g[i].append(c)
        g[c].append(i)
hld = HeavyLightDecomposition(g)
Q = int(input())
for _ in range(Q):
    u, v = map(int, input().split())
    print(hld.lca(u, v))

Solution (Python):
import sys
if sys.version[0] == '2':
    range, input = xrange, raw_input


class Edge:
    def __init__(self, dst, weight):
        self.dst, self.weight = dst, weight

    def __lt__(self, e):
        return self.weight > e.weight


class Graph:
    def __init__(self, V):
        self.V = V
        self.E = [[] for _ in range(V)]

    def add_edge(self, src, dst, weight):
        self.E[src].append(Edge(dst, weight))


class HeavyLightDecomposition:
    def __init__(self, g, root=0):
        self.g = g
        self.vid, self.head, self.heavy, self.parent = [0] * g.V, [-1] * g.V, [-1] * g.V, [-1] * g.V
        self.dfs(root)
        self.bfs(root)

    def dfs(self, root):
        stack = [(root, -1)]
        sub, max_sub = [1] * self.g.V, [(0, -1)] * self.g.V
        used = [False] * self.g.V

        while stack:
            v, par = stack.pop()
            if not used[v]:
                used[v] = True
                self.parent[v] = par
                stack.append((v, par))
                stack.extend((e.dst, v) for e in self.g.E[v] if e.dst != par)
            else:
                if par != -1:
                    sub[par] += sub[v]
                    max_sub[par] = max(max_sub[par], (sub[v], v))
                self.heavy[v] = max_sub[v][1]

    def bfs(self, root=0):
        from collections import deque
        k, que = 0, deque([root])
        while que:
            r = v = que.popleft()
            while v != -1:
                self.vid[v], self.head[v] = k, r
                for e in self.g.E[v]:
                    if e.dst != self.parent[v] and e.dst != self.heavy[v]:
                        que.append(e.dst)
                k += 1
                v = self.heavy[v]

    def lca(self, u, v):
        while self.head[u] != self.head[v]:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
            v = self.parent[self.head[v]]
        else:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
        return u

N = int(input())
g = Graph(N)
for i in range(N):
    for c in map(int, input().split()[1:]):
        g.add_edge(i, c, 1)
        g.add_edge(c, i, 1)
hld = HeavyLightDecomposition(g)
Q = int(input())
for _ in range(Q):
    u, v = map(int, input().split())
    print(hld.lca(u, v))

Solution (Python):
import sys
if sys.version[0] == '2':
    range, input = xrange, raw_input

class HeavyLightDecomposition:
    def __init__(self, g, root=0):
        self.g = g
        self.vid, self.head, self.heavy, self.parent = [0] * len(g), [-1] * len(g), [-1] * len(g), [-1] * len(g)
        self.dfs(root)
        self.bfs(root)
 
    def dfs(self, root):
        stack = [(root, -1)]
        sub, max_sub = [1] * len(self.g), [(0, -1)] * len(self.g)
        used = [False] * len(self.g)
 
        while stack:
            v, par = stack.pop()
            if not used[v]:
                used[v] = True
                self.parent[v] = par
                stack.append((v, par))
                stack.extend((c, v) for c in self.g[v] if c != par)
            else:
                if par != -1:
                    sub[par] += sub[v]
                    max_sub[par] = max(max_sub[par], (sub[v], v))
                self.heavy[v] = max_sub[v][1]
 
    def bfs(self, root=0):
        from collections import deque
        k, que = 0, deque([root])
        while que:
            r = v = que.popleft()
            while v != -1:
                self.vid[v], self.head[v] = k, r
                for c in self.g[v]:
                    if c != self.parent[v] and c != self.heavy[v]:
                        que.append(c)
                k += 1
                v = self.heavy[v]
 
    def lca(self, u, v):
        while self.head[u] != self.head[v]:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
            v = self.parent[self.head[v]]
        else:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
        return u
 
N = int(input())
g = [[] for _ in range(N)]
for i in range(N):
    for c in map(int, input().split()[1:]):
        g[i].append(c)
        g[c].append(i)
hld = HeavyLightDecomposition(g)
Q = int(input())
for _ in range(Q):
    u, v = map(int, input().split())
    print(hld.lca(u, v))

Solution (Python):
import sys
if sys.version[0] == '2':
    range, input = xrange, raw_input


class Edge:
    def __init__(self, dst, weight):
        self.dst, self.weight = dst, weight

    def __lt__(self, e):
        return self.weight > e.weight


class Graph:
    def __init__(self, V):
        self.V = V
        self.E = [[] for _ in range(V)]

    def add_edge(self, src, dst, weight):
        self.E[src].append(Edge(dst, weight))


class HeavyLightDecomposition:
    def __init__(self, g, root=0):
        self.g = g
        self.vid, self.head, self.heavy, self.parent = [0] * g.V, [-1] * g.V, [-1] * g.V, [-1] * g.V
        self.dfs(root)
        self.bfs(root)

    def dfs(self, root):
        stack = [(root, -1, False)]
        sub, max_sub = [1] * self.g.V, [(0, -1)] * self.g.V
        while stack:
            v, par, flag = stack.pop()
            if not flag:
                self.parent[v] = par
                stack.append((v, par, True))
                stack.extend((e.dst, v, False) for e in self.g.E[v] if e.dst != par)
            else:
                if par != -1:
                    sub[par] += sub[v]
                    max_sub[par] = max(max_sub[par], (sub[v], v))
                self.heavy[v] = max_sub[v][1]

    def bfs(self, root=0):
        from collections import deque
        k, que = 0, deque([root])
        while que:
            r = v = que.popleft()
            while v != -1:
                self.vid[v], self.head[v] = k, r
                for e in self.g.E[v]:
                    if e.dst != self.parent[v] and e.dst != self.heavy[v]:
                        que.append(e.dst)
                k += 1
                v = self.heavy[v]

    def lca(self, u, v):
        while self.head[u] != self.head[v]:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
            v = self.parent[self.head[v]]
        else:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
        return u

N = int(input())
g = Graph(N)
for i in range(N):
    for c in map(int, input().split()[1:]):
        g.add_edge(i, c, 1)
        g.add_edge(c, i, 1)
hld = HeavyLightDecomposition(g)
Q = int(input())
for _ in range(Q):
    u, v = map(int, input().split())
    print(hld.lca(u, v))

Solution (Python):
import sys
if sys.version[0] == '2':
    range, input = xrange, raw_input


class HeavyLightDecomposition:
    def __init__(self, g, root=0):
        self.g = g
        self.vid, self.head, self.heavy, self.parent = [0] * len(g), [-1] * len(g), [-1] * len(g), [-1] * len(g)
        self.dfs(root)
        self.bfs(root)

    def dfs(self, root):
        stack = [(root, -1, False)]
        sub, max_sub = [1] * len(self.g), [(0, -1)] * len(self.g)
        while stack:
            v, par, flag = stack.pop()
            if not flag:
                self.parent[v] = par
                stack.append((v, par, True))
                stack.extend((c, v, False) for c in self.g[v] if c != par)
            else:
                if par != -1:
                    sub[par] += sub[v]
                    max_sub[par] = max(max_sub[par], (sub[v], v))
                self.heavy[v] = max_sub[v][1]

    def bfs(self, root=0):
        from collections import deque
        k, que = 0, deque([root])
        while que:
            r = v = que.popleft()
            while v != -1:
                self.vid[v], self.head[v] = k, r
                for c in self.g[v]:
                    if c != self.parent[v] and c != self.heavy[v]:
                        que.append(c)
                k += 1
                v = self.heavy[v]

    def lca(self, u, v):
        while self.head[u] != self.head[v]:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
            v = self.parent[self.head[v]]
        else:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
        return u

N = int(input())
g = [[] for _ in range(N)]
for i in range(N):
    for c in map(int, input().split()[1:]):
        g[i].append(c)
        g[c].append(i)
hld = HeavyLightDecomposition(g)
Q = int(input())
for _ in range(Q):
    u, v = map(int, input().split())
    print(hld.lca(u, v))

Solution (Python):
import sys
if sys.version[0] == '2':
    range, input = xrange, raw_input


class HeavyLightDecomposition:
    def __init__(self, g, root=0):
        self.g = g
        self.vid, self.head, self.heavy, self.parent = [0] * len(g), [-1] * len(g), [-1] * len(g), [-1] * len(g)
        self.dfs(root)
        self.bfs(root)

    def dfs(self, root):
        stack = [(root, -1, False)]
        sub, max_sub = [1] * len(self.g), [(0, -1)] * len(self.g)
        while stack:
            v, par, flag = stack.pop()
            if not flag:
                self.parent[v] = par
                stack.append((v, par, True))
                stack.extend((c, v, False) for c in self.g[v] if c != par)
            else:
                if par != -1:
                    sub[par] += sub[v]
                    max_sub[par] = max(max_sub[par], (sub[v], v))
                self.heavy[v] = max_sub[v][1]

    def bfs(self, root=0):
        from collections import deque
        k, que = 0, deque([root])
        while que:
            r = v = que.popleft()
            while v != -1:
                self.vid[v], self.head[v] = k, r
                for c in self.g[v]:
                    if c != self.parent[v] and c != self.heavy[v]:
                        que.append(c)
                k += 1
                v = self.heavy[v]

    def lca(self, u, v):
        while self.head[u] != self.head[v]:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
            v = self.parent[self.head[v]]
        else:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
        return u

N = int(input())
g = [[] for _ in range(N)]
for i in range(N):
    for c in map(int, input().split()[1:]):
        g[i].append(c)
        g[c].append(i)
hld = HeavyLightDecomposition(g)
Q = int(input())
for _ in range(Q):
    u, v = map(int, input().split())
    print(hld.lca(u, v))

Solution (Python):
import sys
if sys.version[0] == '2':
    range, input = xrange, raw_input


class HeavyLightDecomposition:
    def __init__(self, g, root=0):
        self.g = g
        self.vid, self.head, self.heavy, self.parent = [0] * len(g), [-1] * len(g), [-1] * len(g), [-1] * len(g)
        self.dfs(root)
        self.bfs(root)

    def dfs(self, root):
        stack = [(root, -1, False)]
        sub, max_sub = [1] * len(self.g), [(0, -1)] * len(self.g)
        while stack:
            v, par, flag = stack.pop()
            if not flag:
                self.parent[v] = par
                stack.append((v, par, True))
                stack.extend((c, v, False) for c in self.g[v] if c != par)
            else:
                if par != -1:
                    sub[par] += sub[v]
                    if sub[v] > max_sub[par][0]:
                        max_sub[par] = max(max_sub[par], (sub[v], v))
                self.heavy[v] = max_sub[v][1]

    def bfs(self, root=0):
        from collections import deque
        k, que = 0, deque([root])
        while que:
            r = v = que.popleft()
            while v != -1:
                self.vid[v], self.head[v] = k, r
                for c in self.g[v]:
                    if c != self.parent[v] and c != self.heavy[v]:
                        que.append(c)
                k += 1
                v = self.heavy[v]

    def lca(self, u, v):
        while self.head[u] != self.head[v]:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
            v = self.parent[self.head[v]]
        else:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
        return u

N = int(input())
g = [[] for _ in range(N)]
for i in range(N):
    for c in map(int, input().split()[1:]):
        g[i].append(c)
        g[c].append(i)
hld = HeavyLightDecomposition(g)
Q = int(input())
for _ in range(Q):
    u, v = map(int, input().split())
    print(hld.lca(u, v))

Solution (Python):
import sys
if sys.version[0] == '2':
    range, input = xrange, raw_input


class HeavyLightDecomposition:
    def __init__(self, g, root=0):
        self.g = g
        self.vid, self.head, self.heavy, self.parent = [0] * len(g), [-1] * len(g), [-1] * len(g), [-1] * len(g)
        self.dfs(root)
        self.bfs(root)

    def dfs(self, root):
        stack = [(root, -1)]
        sub, max_sub = [1] * len(self.g), [(0, -1)] * len(self.g)
        used = [False] * len(self.g)
        while stack:
            v, par = stack.pop()
            if not used[v]:
                self.parent[v] = par
                used[v] = True
                stack.append((v, par))
                stack.extend((c, v) for c in self.g[v] if c != par)
            else:
                if par != -1:
                    sub[par] += sub[v]
                    if sub[v] > max_sub[par][0]:
                        max_sub[par] = max(max_sub[par], (sub[v], v))
                self.heavy[v] = max_sub[v][1]

    def bfs(self, root=0):
        from collections import deque
        k, que = 0, deque([root])
        while que:
            r = v = que.popleft()
            while v != -1:
                self.vid[v], self.head[v] = k, r
                for c in self.g[v]:
                    if c != self.parent[v] and c != self.heavy[v]:
                        que.append(c)
                k += 1
                v = self.heavy[v]

    def lca(self, u, v):
        while self.head[u] != self.head[v]:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
            v = self.parent[self.head[v]]
        else:
            if self.vid[u] > self.vid[v]:
                u, v = v, u
        return u

N = int(input())
g = [[] for _ in range(N)]
for i in range(N):
    for c in map(int, input().split()[1:]):
        g[i].append(c)
        g[c].append(i)
hld = HeavyLightDecomposition(g)
Q = int(input())
for _ in range(Q):
    u, v = map(int, input().split())
    print(hld.lca(u, v))

Solution (Python):
from math import log2


def build():
    dfs()
    pk0 = parent[0]
    for k in range(1, logn):
        pk1 = parent[k]
        for v in range(n):
            pkv = pk0[v]
            pk1[v] = -1 if pkv < 0 else pk0[pkv]
        pk0 = pk1


def dfs():
    stack = [(0, -1, 0)]
    while stack:
        v, p, d = stack.pop()
        parent[0][v] = p
        depth[v] = d
        stack.extend((child, v, d + 1) for child in tree[v])


def get(u, v):
    du, dv = depth[u], depth[v]
    if du > dv:
        u, v = v, u
        du, dv = dv, du
    for k in range(logn):
        if (dv - du) >> k & 1:
            v = parent[k][v]
    if u == v:
        return u
    for k in range(logn - 1, -1, -1):
        pk = parent[k]
        if pk[u] != pk[v]:
            u, v = pk[u], pk[v]
    return parent[0][u]


n = int(input())
tree = [set(map(int, input().split()[1:])) for _ in range(n)]

logn = int(log2(n)) + 1
parent = [[0] * n for _ in range(logn)]
depth = [0] * n
build()

q = int(input())
for _ in range(q):
    print(get(*map(int, input().split())))

Solution (Python):
from math import log2


def build():
    dfs()
    pk0 = parent[0]
    for pk1 in parent[1:]:
        for v in range(n):
            pkv = pk0[v]
            pk1[v] = -1 if pkv < 0 else pk0[pkv]
        pk0 = pk1


def dfs():
    stack = [(0, -1, 0)]
    while stack:
        v, p, d = stack.pop()
        parent[0][v] = p
        depth[v] = d
        stack.extend((child, v, d + 1) for child in tree[v])


def get(u, v):
    du, dv = depth[u], depth[v]
    if du > dv:
        u, v = v, u
        du, dv = dv, du
    for k, pk in enumerate(parent):
        if (dv - du) >> k & 1:
            v = pk[v]
    if u == v:
        return u
    for pk in parent[logn - 1:None:-1]:
        pku, pkv = pk[u], pk[v]
        if pku != pkv:
            u, v = pku, pkv
    return parent[0][u]


n = int(input())
tree = [set(map(int, input().split()[1:])) for _ in range(n)]

logn = int(log2(n)) + 1
parent = [[0] * n for _ in range(logn)]
depth = [0] * n
build()

q = int(input())
for _ in range(q):
    print(get(*map(int, input().split())))

Solution (Python):
from collections import deque
n = input()

C = [None]*n
P = [None]*n
for i in xrange(n):
    ipt = map(int, raw_input().split())
    C[i] = ipt[1:]
    for c in C[i]:
        P[c] = i
LEV = (n+1).bit_length()
parent = [[None]*(LEV + 1) for i in xrange(n)]
for i in xrange(n):
    parent[i][0] = P[i]
for k in xrange(LEV):
    for i in xrange(n):
        if parent[i][k] is None:
            parent[i][k+1] = None
        else:
            parent[i][k+1] = parent[parent[i][k]][k]
depth = [None]*n
deq = deque()
deq.append(0)
depth[0] = 0
while deq:
    v = deq.popleft()
    for c in C[v]:
        deq.append(c)
        depth[c] = depth[v] + 1

q = input()
for t in xrange(q):
    u, v = map(int, raw_input().split())
    if not depth[u] < depth[v]:
        u, v = v, u
    for k in xrange(LEV+1):
        if ((depth[v] - depth[u]) >> k) & 1:
            v = parent[v][k]
    if u == v:
        print u
        continue

    for k in xrange(LEV, -1, -1):
        if parent[u][k] != parent[v][k]:
            u = parent[u][k]
            v = parent[v][k]
    print parent[u][0]

Solution (Python):
import math
import sys
from collections import defaultdict
sys.setrecursionlimit(200000)

def dfs(here, p, d, parent, depth, connect):
    parent[0][here] = p
    depth[here] = d
    for next_v in connect[here]:
        dfs(next_v, here, d + 1, parent, depth, connect)

def lca(v1, v2, parent, depth):
    if depth[v2] > depth[v1]:
        v1, v2 = v2, v1
    for i in range(max_log):
        if depth[v1] - depth[v2] >> i & 1:
            v1 = parent[i][v1]
    if v1 == v2:
        return v2
    for i in range(max_log - 1, -1, -1):
        if parent[i][v1] != parent[i][v2]:
            v1 = parent[i][v1]
            v2 = parent[i][v2]
    return parent[0][v1]

connect = defaultdict(list)
v_num = int(input())
root = 0
for i in range(v_num):
    edge = [int(n) for n in input().split(" ")]
    connect[i].extend(edge[1:])
depth = [-1 for n in range(v_num)]
max_log = max(int(math.log(v_num, 2)), 1)
parent = [[-1 for n in range(v_num)] for m in range(max_log)]
dfs(root, -1, 0, parent, depth, connect)
for i in range(max_log - 1):
    for v in range(v_num):
        parent[i + 1][v] = -1 if parent[i][v] < 0 else parent[i][parent[i][v]]
q_num = int(input())
for _ in range(q_num):
    v1, v2 = (int(n) for n in input().split(" ") )
    print(lca(v1, v2, parent, depth))

Solution (Python):


import math
import sys
from collections import defaultdict
sys.setrecursionlimit(200000)

def dfs(here, p, d, parent, depth, connect):
    parent[0][here] = p
    depth[here] = d
    for next_v in connect[here]:
        dfs(next_v, here, d + 1, parent, depth, connect)

def lca(v1, v2, parent, depth):
    if depth[v2] > depth[v1]:
        v1, v2 = v2, v1
    for i in range(max_log):
        if depth[v1] - depth[v2] >> i & 1:
            v1 = parent[i][v1]
    if v1 == v2:
        return v2
    for i in range(max_log - 1, -1, -1):
        if parent[i][v1] != parent[i][v2]:
            v1 = parent[i][v1]
            v2 = parent[i][v2]
    return parent[0][v1]

connect = defaultdict(list)
v_num = int(input())
root = 0
for i in range(v_num):
    edge = [int(n) for n in input().split(" ")]
    connect[i].extend(edge[1:])
depth = [-1 for n in range(v_num)]
max_log = max(int(math.log(v_num, 2)), 1)
parent = [[-1 for n in range(v_num)] for m in range(max_log)]
dfs(root, -1, 0, parent, depth, connect)
for i in range(max_log - 1):
    for v in range(v_num):
        parent[i + 1][v] = -1 if parent[i][v] < 0 else parent[i][parent[i][v]]
q_num = int(input())
for _ in range(q_num):
    v1, v2 = (int(n) for n in input().split(" ") )
    print(lca(v1, v2, parent, depth))