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

// Lowest Common Ancestor
// 最小共通先祖
// 二部探索を用いる方法

#include <bits/stdc++.h>
using namespace std;
#define MAX_V 100010
#define MAX_LOG_V 100
vector<int> G[MAX_V]; // グラフの隣接リスト
int root;             // 根の頂点番号
int parent[MAX_LOG_V]
          [MAX_V]; // parent[i][j] := 頂点jから2^i親をたどって到達する頂点
int depth[MAX_V]; // 根からの深さ

void dfs(int v, int p, int d) {
  parent[0][v] = p;
  depth[v] = d;

  for (int i = 0; i < G[v].size(); i++) {
    if (G[v][i] != p)
      dfs(G[v][i], v, d + 1);
  }
}

void init(int V) {
  // parent[0]とdepthを初期化する
  dfs(root, -1, 0);
  // parentを初期化する
  for (int k = 0; k + 1 < MAX_LOG_V; k++) {
    for (int v = 0; v < V; v++) {
      if (parent[k][v] < 0)
        parent[k + 1][v] = -1;
      else
        parent[k + 1][v] = parent[k][parent[k][v]];
    }
  }
}

// uとvのLCAを求める
int lca(int u, int v) {
  // uとvの深さが同じになるまで親をたどる
  if (depth[u] > depth[v])
    swap(u, v);
  for (int k = 0; k < MAX_LOG_V; k++) {
    if ((depth[v] - depth[u] >> k) & 1) { // これあテクい
      v = parent[k][v];
    }
  }

  if (u == v)
    return u;

  // 二部探索でLCAを求める
  for (int k = MAX_LOG_V - 1; k >= 0; k--) {
    if (parent[k][u] != parent[k][v]) {
      u = parent[k][u];
      v = parent[k][v];
    }
  }

  return parent[0][u]; // uの親を返す
}

int main() {

  // 0-indexed
  root = 0;
  int V;
  cin >> V;
  for (int i = 1; i < V; i++) {
    int a;
    cin >> a;
    a--;
    G[i].push_back(a);
    G[a].push_back(i);
  }

  init(V);

  vector<int> a; // 訪れる頂点の順番
  queue<int> q;
  q.push(0);
  vector<bool> used(V, false);
  used[0] = true;

  while (!q.empty()) {
    int next = q.front();
    q.pop();

    a.push_back(next);

    for (int i = 0; i < G[next].size(); i++) {
      if (!used[G[next][i]]) {
        used[G[next][i]] = true;
        q.push(G[next][i]);
      }
    }
  }

  /*for(int i = 0; i < a.size(); i++){
      cout << a[i] << " ";
  }
  cout << endl;*/

  long long ans = 0;
  for (int i = 1; i < a.size(); i++) {

    int u = a[i - 1];
    int v = a[i];
    int LCA = lca(u, v);
    // cout << u << " " << v << " " << LCA << endl;
    ans += (long long)(depth[u] + depth[v] - 2 * depth[LCA]);
  }

  cout << ans << endl;

  return 0;
}


Error: 0

Fixed submission:

// Lowest Common Ancestor
// 最小共通先祖
// 二部探索を用いる方法

#include <bits/stdc++.h>
using namespace std;
#define MAX_V 10000
#define MAX_LOG_V 100
vector<int> G[MAX_V]; // グラフの隣接リスト
int root;             // 根の頂点番号
int parent[MAX_LOG_V]
          [MAX_V]; // parent[i][j] := 頂点jから2^i親をたどって到達する頂点
int depth[MAX_V]; // 根からの深さ

void dfs(int v, int p, int d) {
  parent[0][v] = p;
  depth[v] = d;

  for (int i = 0; i < G[v].size(); i++) {
    if (G[v][i] != p)
      dfs(G[v][i], v, d + 1);
  }
}

void init(int V) {
  // parent[0]とdepthを初期化する
  dfs(root, -1, 0);
  // parentを初期化する
  for (int k = 0; k + 1 < MAX_LOG_V; k++) {
    for (int v = 0; v < V; v++) {
      if (parent[k][v] < 0)
        parent[k + 1][v] = -1;
      else
        parent[k + 1][v] = parent[k][parent[k][v]];
    }
  }
}

// uとvのLCAを求める
int lca(int u, int v) {
  // uとvの深さが同じになるまで親をたどる
  if (depth[u] > depth[v])
    swap(u, v);
  for (int k = 0; k < MAX_LOG_V; k++) {
    if ((depth[v] - depth[u] >> k) & 1) { // これあテクい
      v = parent[k][v];
    }
  }

  if (u == v)
    return u;

  // 二部探索でLCAを求める
  for (int k = MAX_LOG_V - 1; k >= 0; k--) {
    if (parent[k][u] != parent[k][v]) {
      u = parent[k][u];
      v = parent[k][v];
    }
  }

  return parent[0][u]; // uの親を返す
}

int main() {

  // 0-indexed
  root = 0;
  int V;
  cin >> V;
  for (int i = 1; i < V; i++) {
    int a;
    cin >> a;
    a--;
    G[i].push_back(a);
    G[a].push_back(i);
  }

  init(V);

  vector<int> a; // 訪れる頂点の順番
  queue<int> q;
  q.push(0);
  vector<bool> used(V, false);
  used[0] = true;

  while (!q.empty()) {
    int next = q.front();
    q.pop();

    a.push_back(next);

    for (int i = 0; i < G[next].size(); i++) {
      if (!used[G[next][i]]) {
        used[G[next][i]] = true;
        q.push(G[next][i]);
      }
    }
  }

  /*for(int i = 0; i < a.size(); i++){
      cout << a[i] << " ";
  }
  cout << endl;*/

  int ans = 0;
  for (int i = 1; i < a.size(); i++) {

    int u = a[i - 1];
    int v = a[i];
    int LCA = lca(u, v);
    // cout << u << " " << v << " " << LCA << endl;
    ans += depth[u] + depth[v] - 2 * depth[LCA];
  }

  cout << ans << endl;

  return 0;
}