AtCoder problem 035

C++ solution:
#include <vector>

#include <iostream>

#include <algorithm>

#include <functional>

using namespace std;

int main() {

	cin.tie(0);

	ios_base::sync_with_stdio(false);

	int N;

	cin >> N;

	vector<vector<int> > G(N);

	for (int i = 0; i < N - 1; ++i) {

		int A, B;

		cin >> A >> B; --A, --B;

		G[A].push_back(B);

		G[B].push_back(A);

	}

	int bits = 0;

	while ((1 << bits) < N) ++bits;

	vector<vector<int> > par(bits, vector<int>(N));

	vector<int> depth(N), id(N);

	int vert_id = 0;

	function<void(int, int)> build_tree = [&](int pos, int pre) {

		par[0][pos] = pre;

		id[pos] = vert_id++;

		for (int i : G[pos]) {

			if (i == pre) continue;

			depth[i] = depth[pos] + 1;

			build_tree(i, pos);

		}

	};

	build_tree(0, 0);

	for (int i = 1; i < bits; ++i) {

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

			par[i][j] = par[i - 1][par[i - 1][j]];

		}

	}

	function<int(int, int)> lca = [&](int va, int vb) {

		if (depth[va] < depth[vb]) swap(va, vb);

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

			if (depth[va] - depth[vb] >= (1 << i)) {

				va = par[i][va];

			}

		}

		if (va == vb) return va;

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

			if (par[i][va] != par[i][vb]) {

				va = par[i][va];

				vb = par[i][vb];

			}

		}

		return par[0][va];

	};

	int Q;

	cin >> Q;

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

		int verts;

		cin >> verts;

		vector<int> sel(verts);

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

			cin >> sel[j];

			--sel[j];

		}

		sort(sel.begin(), sel.end(), [&](int va, int vb) {

			return id[va] < id[vb];

			});

		int answer = 0;

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

			answer += depth[sel[j]];

			answer -= depth[lca(sel[j], sel[(j + 1) % verts])];

		}

		cout << answer << '\n';

	}

	return 0;

}

Crystal solution: class UnweightedGraph
  getter graph : Array(Array(Int32))

  def initialize(size : Int)
    @graph = Array.new(size) { Array(Int32).new }
  end

  def add_edge(v, u)
    @graph[v] << u
    @graph[u] << v
  end

  delegate size, to: @graph
  delegate :[], to: @graph

  def pre_order(root : Int32)
    result = Array(Int32).new(size)
    stack = Deque{ {root, -1} }
    while vp = stack.pop?
      vertex, parent = vp
      result << vertex
      self[vertex].reverse_each do |to|
        stack << {to, vertex} if to != parent
      end
    end
    result
  end
end

class LCA
  getter graph : UnweightedGraph
  getter depth : Array(Int32)

  private def dfs(vertex : Int32, par : Int32, dep : Int32) : Nil
    @parent[0][vertex] = par
    @depth[vertex] = dep
    @graph[vertex].each do |edge|
      dfs(edge, vertex, dep + 1) if edge != par
    end
  end

  def initialize(@graph, root : Int32)
    @log2 = Math.log2(size).to_i.succ.as(Int32)
    @depth = Array(Int32).new(size, -1)
    @parent = Array(Array(Int32)).new(@log2) { Array.new(size, 0) }
    dfs(root, -1, 0)
    (0...@log2 - 1).each do |k|
      (0...size).each do |v|
        if @parent[k][v] < 0
          @parent[k + 1][v] = -1
        else
          @parent[k + 1][v] = @parent[k][@parent[k][v]]
        end
      end
    end
  end

  delegate size, to: @graph

  def lca(u : Int32, v : Int32) : Int32
    u, v = v, u if @depth[u] > @depth[v]
    (0...@log2).each do |k|
      v = @parent[k][v] if (@depth[v] - @depth[u]).bit(k) == 1
    end

    return u if u == v

    (0...@log2).reverse_each do |k|
      u, v = @parent[k][u], @parent[k][v] if @parent[k][u] != @parent[k][v]
    end
    @parent[0][u]
  end

  def dist(u : Int32, v : Int32) : Int32
    @depth[u] + @depth[v] - @depth[lca(u, v)] * 2
  end
end

n = read_line.to_i
graph = UnweightedGraph.new(n)
n.pred.times do
  a, b = read_line.split.map(&.to_i.pred)
  graph.add_edge(a, b)
end
lca = LCA.new(graph, 0)

order = graph.pre_order(0)
index = [0] * n
(0...n).each { |i| index[order[i]] = i }

read_line.to_i.times do
  v = read_line.split.map(&.to_i.pred).skip(1).sort_by! { |i| index[i] }
  puts (0...v.size).sum { |i| lca.dist v[i], v[i.succ % v.size] } // 2
end