Problem p02373 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = (a); i < (int)(b); ++i)

using pii = pair<int, int>;
using vvi = vector<vector<int>>;
using vi = vector<int>;
#define sz(x) ((int)x.size())

struct UnionFind {
  vi data;
  int comp;
  UnionFind() {}
  UnionFind(int size) { init(size); }
  void init(int size) {
    data.assign(size, -1);
    comp = size;
  }
  void unite(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x])
        swap(x, y);
      data[x] += data[y];
      data[y] = x;
      comp--;
    }
  }
  bool same(int x, int y) { return root(x) == root(y); }
  int root(int x) {
    if (data[x] < 0) {
      return x;
    } else {
      return data[x] = root(data[x]);
    }
  }
  int size(int x) { return -data[root(x)]; }
  int components() { return comp; }
};

template <class Graph> struct LCA {
  using Query = pii;
  Graph g;
  vi color;
  vi ancestor;
  vector<vector<pair<int, Query>>> query_set;
  vi res;
  UnionFind uf;
  LCA(const Graph &g, vector<Query> &query)
      : g(g), color(sz(g)), ancestor(sz(g)), query_set(sz(query)),
        res(sz(query)), uf(sz(g)) {
    int qs = sz(query);
    rep(i, 0, qs) {
      query_set[query[i].first].emplace_back(i, query[i]);
      query_set[query[i].second].emplace_back(i, query[i]);
    }
  }
  void visit(int s, int prev) {
    ancestor[uf.root(s)] = s;
    for (auto &e : g[s]) {
      if (e == prev) {
        continue;
      }
      visit(e, s);
      uf.unite(s, e);
      ancestor[uf.root(s)] = s;
    }
    color[s] = 1;
    for (auto &p : query_set[s]) {
      Query q = p.second;
      int w = (q.second == s ? q.first : (q.first == s ? q.second : -1));
      if (w == -1 || !color[w]) {
        continue;
      }
      res[p.first] = ancestor[uf.root(w)];
    }
  }
  vi solve(int root) {
    visit(root, -1);
    return res;
  }
};

signed main() {
  int N;
  cin >> N;
  vector<vector<int>> G(N);
  rep(i, 0, N) {
    int K;
    cin >> K;
    rep(k, 0, K) {
      int X;
      cin >> X;
      G[i].push_back(X);
      G[X].push_back(i);
    }
  }
  int Q;
  cin >> Q;
  vector<pii> queries;
  rep(i, 0, Q) {
    int U, V;
    cin >> U >> V;
    queries.emplace_back(U, V);
  }
  LCA<vvi> lca(G, queries);
  vi res = lca.solve(0);

  for (int ans : res) {
    cout << ans << endl;
  }
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = (a); i < (int)(b); ++i)

using pii = pair<int, int>;
using vvi = vector<vector<int>>;
using vi = vector<int>;
#define sz(x) ((int)x.size())

struct UnionFind {
  vi data;
  int comp;
  UnionFind() {}
  UnionFind(int size) { init(size); }
  void init(int size) {
    data.assign(size, -1);
    comp = size;
  }
  void unite(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x])
        swap(x, y);
      data[x] += data[y];
      data[y] = x;
      comp--;
    }
  }
  bool same(int x, int y) { return root(x) == root(y); }
  int root(int x) {
    if (data[x] < 0) {
      return x;
    } else {
      return data[x] = root(data[x]);
    }
  }
  int size(int x) { return -data[root(x)]; }
  int components() { return comp; }
};

template <class Graph> struct LCA {
  using Query = pii;
  Graph g;
  vi color;
  vi ancestor;
  vector<vector<pair<int, Query>>> query_set;
  vi res;
  UnionFind uf;
  LCA(const Graph &g, vector<Query> &query)
      : g(g), color(sz(g)), ancestor(sz(g)), query_set(sz(g)), res(sz(query)),
        uf(sz(g)) {
    int qs = sz(query);
    rep(i, 0, qs) {
      query_set[query[i].first].emplace_back(i, query[i]);
      query_set[query[i].second].emplace_back(i, query[i]);
    }
  }
  void visit(int s, int prev) {
    ancestor[uf.root(s)] = s;
    for (auto &e : g[s]) {
      if (e == prev) {
        continue;
      }
      visit(e, s);
      uf.unite(s, e);
      ancestor[uf.root(s)] = s;
    }
    color[s] = 1;
    for (auto &p : query_set[s]) {
      Query q = p.second;
      int w = (q.second == s ? q.first : (q.first == s ? q.second : -1));
      if (w == -1 || !color[w]) {
        continue;
      }
      res[p.first] = ancestor[uf.root(w)];
    }
  }
  vi solve(int root) {
    visit(root, -1);
    return res;
  }
};

signed main() {
  int N;
  cin >> N;
  vector<vector<int>> G(N);
  rep(i, 0, N) {
    int K;
    cin >> K;
    rep(k, 0, K) {
      int X;
      cin >> X;
      G[i].push_back(X);
      G[X].push_back(i);
    }
  }
  int Q;
  cin >> Q;
  vector<pii> queries;
  rep(i, 0, Q) {
    int U, V;
    cin >> U >> V;
    queries.emplace_back(U, V);
  }
  LCA<vvi> lca(G, queries);
  vi res = lca.solve(0);

  for (int ans : res) {
    cout << ans << endl;
  }
}