Problem p02373 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm>
#include <cmath>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

int N;                 // Graph(Tree)の頂点数
vector<vector<int>> G; // Graph(Tree)の隣接リスト表現
vector<int> D;         // 各頂点のrootからの距離
int LOG_N;             // log2(N)の天井
vector<vector<int>> P; // P[k][v] : 頂点vの2^k番目の先祖
void dfs(int prev, int index, int d) {
  P[0][index] = prev;
  D[index] = d;
  for (int i = 0; i < G[index].size(); i++) {
    int next = G[index][i];
    if (next == prev)
      continue;
    dfs(index, next, d + 1);
  }
}
void init() {
  LOG_N = int(ceil(log2(N) + 1));
  P.clear();
  P.resize(LOG_N, vector<int>(N));
  D.clear();
  D.resize(N);
  dfs(-1, 0, 0);
  for (int k = 0; k < LOG_N - 1; k++) {
    for (int v = 0; v < N; v++) {
      if (P[k][v] < 0)
        P[k + 1][v] = -1;
      else
        P[k + 1][v] = P[k][P[k][v]];
    }
  }
}
// 頂点vのn番目の親を返す
int nth_parent(int v, int n) {
  for (int k = 0; k < LOG_N; k++)
    if (n & (1 << k))
      v = P[k][v];
  return v;
}
// 2頂点uとvのLCAを返す
int lca(int u, int v) {
  if (D[u] > D[v])
    swap(u, v);
  v = nth_parent(v, D[v] - D[u]);
  if (u == v)
    return u;
  for (int k = LOG_N - 1; k >= 0; k--) {
    if (P[k][u] != P[k][v]) {
      u = P[k][u];
      v = P[k][v];
    }
  }
  return P[0][u];
}
// 2頂点uとvの距離を返す
int dist(int u, int v) {
  int root = lca(u, v);
  return (D[u] - D[root]) + (D[v] - D[root]);
}

int main() {
  cin >> N;
  G.clear();
  G.resize(N);
  for (int i = 0; i < N; i++) {
    int k;
    cin >> k;
    for (int j = 0; j < k; j++) {
      int c;
      cin >> c;
      G[i].push_back(c);
    }
  }
  init();
  int Q;
  cin >> Q;
  for (int q = 0; q < Q; q++) {
    int u, v;
    cin >> u >> v;
    cout << lca(u, v) << endl;
  }
  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <cmath>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

int N;                 // Graph(Tree)の頂点数
vector<vector<int>> G; // Graph(Tree)の隣接リスト表現
vector<int> D;         // 各頂点のrootからの距離
int LOG_N;             // log2(N)の天井
vector<vector<int>> P; // P[k][v] : 頂点vの2^k番目の先祖
void dfs(int prev, int index, int d) {
  P[0][index] = prev;
  D[index] = d;
  for (int i = 0; i < G[index].size(); i++) {
    int next = G[index][i];
    if (next == prev)
      continue;
    dfs(index, next, d + 1);
  }
}
void init() {
  LOG_N = int(ceil(log2(N)));
  P.clear();
  P.resize(LOG_N, vector<int>(N));
  D.clear();
  D.resize(N);
  dfs(-1, 0, 0);
  for (int k = 0; k < LOG_N - 1; k++) {
    for (int v = 0; v < N; v++) {
      if (P[k][v] < 0)
        P[k + 1][v] = -1;
      else
        P[k + 1][v] = P[k][P[k][v]];
    }
  }
}
// 頂点vのn番目の親を返す
int nth_parent(int v, int n) {
  for (int k = 0; k < LOG_N; k++)
    if (n & (1 << k))
      v = P[k][v];
  return v;
}
// 2頂点uとvのLCAを返す
int lca(int u, int v) {
  if (D[u] > D[v])
    swap(u, v);
  v = nth_parent(v, D[v] - D[u]);
  if (u == v)
    return u;
  for (int k = LOG_N - 1; k >= 0; k--) {
    if (P[k][u] != P[k][v]) {
      u = P[k][u];
      v = P[k][v];
    }
  }
  return P[0][u];
}
// 2頂点uとvの距離を返す
int dist(int u, int v) {
  int root = lca(u, v);
  return (D[u] - D[root]) + (D[v] - D[root]);
}

int main() {
  cin >> N;
  G.clear();
  G.resize(N);
  for (int i = 0; i < N; i++) {
    int k;
    cin >> k;
    for (int j = 0; j < k; j++) {
      int c;
      cin >> c;
      G[i].push_back(c);
    }
  }
  init();
  int Q;
  cin >> Q;
  for (int q = 0; q < Q; q++) {
    int u, v;
    cin >> u >> v;
    cout << lca(u, v) << endl;
  }
  return 0;
}