Problem p02368 (C++)

Buggy submission (status: Runtime Error):
/*
 * Strongly Connected Components
 * A direced graph is strongly connected if every two nodes are reachable from
 * each other. In a strongly connected component of a directed graph, every two
 * nodes of the component are mutually reachable.
 *
 * Input
 * A directed graph G(V,E) and a sequence of queries where each query contains a
 * pair of nodes u and v.
 *
 * |V| |E|
 * s0 t0
 * s1 t1
 * :
 * s|E|−1 t|E|−1
 * Q
 * u0 v0
 * u1 v1
 * :
 * uQ−1 vQ−1
 * |V| is the number of nodes and |E| is the number of edges in the graph. The
 * graph nodes are named with the numbers 0, 1,..., |V|-1 respectively.
 *
 * si and ti represent source and target nodes of i-th edge (directed).
 *
 * ui and vi represent a pair of nodes given as the i-th query.
 *
 * Output
 * For each query, pinrt "1" if the given nodes belong to the same strongly
 * connected component, "0" otherwise.
 *
 * Constraints
 * 1 ≤ |V| ≤ 10,000
 * 0 ≤ |E| ≤ 30,000
 * 1 ≤ Q ≤ 100,000
 */

#include <algorithm>
#include <functional>
#include <iostream>
#include <stack>
#include <vector>

#define MAXN 10010
#define MAXM 30030

using namespace std;

struct edge {
  int to, next;
};

bool visited[MAXN];

void dfs(int i, vector<edge> &E, vector<int> &LE,
         const function<void(int)> &preprocess,
         const function<void(int)> &postprocess) {
  if (visited[i])
    return;
  visited[i] = true;
  preprocess(i);
  for (int e = LE[i]; e != -1; e = E[e].next)
    dfs(E[e].to, E, LE, preprocess, postprocess);
  postprocess(i);
}

int main() {
  vector<int> LE(MAXN, -1), LErev(MAXN, -1);
  vector<edge> E(MAXN), Erev(MAXN + MAXM);

  int n, m;
  cin >> n >> m;
  for (int src, dst, i = 0; i < m; ++i) {
    cin >> src >> dst;
    E[i] = {dst, LE[src]};
    LE[src] = i;
    Erev[i] = {src, LErev[dst]};
    LErev[dst] = i;
  }

  // adding dummy node with index n for DFS
  for (int i = m; i < m + n; ++i) {
    Erev[i] = {i - m, LErev[n]};
    LErev[n] = i;
  }

  fill(visited, visited + MAXN, false);
  stack<int> grev_post; // pop off in descending postnumber order in Grev
  dfs(
      n, Erev, LErev, [](int x) { return; }, [&](int x) { grev_post.push(x); });
  grev_post.pop(); // dummy node

  vector<int> scc(n);
  fill(visited, visited + MAXN, false);
  for (int i = 1; !grev_post.empty(); ++i) {
    while (!grev_post.empty() && scc[grev_post.top()])
      grev_post.pop();
    if (grev_post.empty())
      break;
    dfs(
        grev_post.top(), E, LE, [&](int x) { scc[x] = i; },
        [](int x) { return; });
  }

  int q;
  cin >> q;
  for (int s, t; cin >> s >> t;) {
    cout << (scc[s] == scc[t]) << endl;
  }
}


Fixed submission:
/*
 * Strongly Connected Components
 * A direced graph is strongly connected if every two nodes are reachable from
 * each other. In a strongly connected component of a directed graph, every two
 * nodes of the component are mutually reachable.
 *
 * Input
 * A directed graph G(V,E) and a sequence of queries where each query contains a
 * pair of nodes u and v.
 *
 * |V| |E|
 * s0 t0
 * s1 t1
 * :
 * s|E|−1 t|E|−1
 * Q
 * u0 v0
 * u1 v1
 * :
 * uQ−1 vQ−1
 * |V| is the number of nodes and |E| is the number of edges in the graph. The
 * graph nodes are named with the numbers 0, 1,..., |V|-1 respectively.
 *
 * si and ti represent source and target nodes of i-th edge (directed).
 *
 * ui and vi represent a pair of nodes given as the i-th query.
 *
 * Output
 * For each query, pinrt "1" if the given nodes belong to the same strongly
 * connected component, "0" otherwise.
 *
 * Constraints
 * 1 ≤ |V| ≤ 10,000
 * 0 ≤ |E| ≤ 30,000
 * 1 ≤ Q ≤ 100,000
 */

#include <algorithm>
#include <functional>
#include <iostream>
#include <stack>
#include <vector>

#define MAXN 10010
#define MAXM 30030

using namespace std;

struct edge {
  int to, next;
};

bool visited[MAXN];

void dfs(int i, vector<edge> &E, vector<int> &LE,
         const function<void(int)> &preprocess,
         const function<void(int)> &postprocess) {
  if (visited[i])
    return;
  visited[i] = true;
  preprocess(i);
  for (int e = LE[i]; e != -1; e = E[e].next)
    dfs(E[e].to, E, LE, preprocess, postprocess);
  postprocess(i);
}

int main() {
  vector<int> LE(MAXN, -1), LErev(MAXN, -1);
  vector<edge> E(MAXM), Erev(MAXN + MAXM);

  int n, m;
  cin >> n >> m;
  for (int src, dst, i = 0; i < m; ++i) {
    cin >> src >> dst;
    E[i] = {dst, LE[src]};
    LE[src] = i;
    Erev[i] = {src, LErev[dst]};
    LErev[dst] = i;
  }

  // adding dummy node with index n for DFS
  for (int i = m; i < m + n; ++i) {
    Erev[i] = {i - m, LErev[n]};
    LErev[n] = i;
  }

  fill(visited, visited + MAXN, false);
  stack<int> grev_post; // pop off in descending postnumber order in Grev
  dfs(
      n, Erev, LErev, [](int x) { return; }, [&](int x) { grev_post.push(x); });
  grev_post.pop(); // dummy node

  vector<int> scc(n);
  fill(visited, visited + MAXN, false);
  for (int i = 1; !grev_post.empty(); ++i) {
    while (!grev_post.empty() && scc[grev_post.top()])
      grev_post.pop();
    if (grev_post.empty())
      break;
    dfs(
        grev_post.top(), E, LE, [&](int x) { scc[x] = i; },
        [](int x) { return; });
  }

  int q;
  cin >> q;
  for (int s, t; cin >> s >> t;) {
    cout << (scc[s] == scc[t]) << endl;
  }
}