Problem p02373 (C++) — buggy submission, verdict: Memory Limit Exceeded

// Lowest Common Ancestor
// 最小共通先祖
// 二部探索を用いる方法
/*
int main(){
    int n; cin >> n;
    vector<int> a(n);
    for(int i = 0; i < n; i++) cin >> a[i];
    a = max(a, b);
    a = max(max(a, b), max(c, d));

}*/

#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
  int V;
  cin >> V;
  root = 0;
  for (int i = 0; i < V; i++) {
    int k;
    cin >> k;
    for (int j = 0; j < k; j++) {
      int c;
      cin >> c;
      G[i].push_back(c);
      G[c].push_back(i);
    }
  }
  init(V);
  int q;
  cin >> q;

  for (int i = 0; i < q; i++) {
    int u, v;
    cin >> u >> v;
    cout << lca(u, v) << endl;
  }

  return 0;
}


Error: MLE

Fixed submission:

// Lowest Common Ancestor
// 最小共通先祖
// 二部探索を用いる方法
/*
int main(){
    int n; cin >> n;
    vector<int> a(n);
    for(int i = 0; i < n; i++) cin >> a[i];
    a = max(a, b);
    a = max(max(a, b), max(c, d));

}*/

#include <bits/stdc++.h>
using namespace std;
#define MAX_V 100010
#define MAX_LOG_V 500
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
  int V;
  cin >> V;
  root = 0;
  for (int i = 0; i < V; i++) {
    int k;
    cin >> k;
    for (int j = 0; j < k; j++) {
      int c;
      cin >> c;
      G[i].push_back(c);
      G[c].push_back(i);
    }
  }
  init(V);
  int q;
  cin >> q;

  for (int i = 0; i < q; i++) {
    int u, v;
    cin >> u >> v;
    cout << lca(u, v) << endl;
  }

  return 0;
}