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

// Name: Railroad
// Level: 4
// Category: グラフ,Graph,最短経路,DAG
// Note:

/**
 * AからBまでの最短経路をDijkstra法で求め、そのときに使った辺のみから
 * なるDAGを構成する。
 * すると、cからdに最短経路で行けるかの判定は、このDAG上でcからdに行けるかの
 * 判定と等価になる。
 * 1クエリについて最悪全ノードの探索が必要で、これはO(N+M)になるが、
 * 到達可能かどうかは1bitしか使わないのでbit parallelで高速化ができる。
 * (N+M) × Q = 10^10 程度なので、数十倍程度の高速化をすれば制限時間に間に合う。
 *
 * オーダーは O(N log R + (N+M)Q)。
 */
#include <algorithm>
#include <array>
#include <bitset>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef bitset<128> Flag;
const LL INF = 100000LL * 1000 * 10;

bool solve() {
  int S, R;
  if (!(cin >> S >> R))
    return false;
  if (!S && !R)
    return false;

  array<vector<pair<int, LL>>, 100000> graph;
  array<vector<int>, 100000> dag;
  for (int i = 0; i < R; ++i) {
    int u, v, w;
    cin >> u >> v >> w;
    --u;
    --v;
    graph[u].push_back(make_pair(v, w));
    graph[v].push_back(make_pair(u, w));
  }
  int A, B, Q;
  cin >> A >> B >> Q;
  --A;
  --B;

  // Find shortest path
  array<LL, 100000> memo;
  priority_queue<pair<LL, int>> q;
  LL best_cost = INF;
  fill(memo.begin(), memo.end(), INF);
  q.push(make_pair(0, A));
  memo[A] = 0;
  while (!q.empty()) {
    const LL cost = -q.top().first;
    const int cur = q.top().second;
    q.pop();
    if (cost > best_cost)
      break;
    if (cur == B && best_cost == INF) {
      best_cost = cost;
    }
    if (memo[cur] < cost)
      continue;
    for (const auto &next : graph[cur]) {
      const LL nc = cost + next.second;
      if (nc < memo[next.first]) {
        dag[next.first].clear();
        dag[next.first].push_back(cur);
        memo[next.first] = nc;
        q.push(make_pair(-nc, next.first));
      } else if (memo[next.first] == nc) {
        dag[next.first].push_back(cur);
      }
    }
  }

  vector<int> ord;
  {
    array<int, 100000> ref_cnt;
    array<bool, 100000> visited;
    fill(visited.begin(), visited.end(), false);
    fill(ref_cnt.begin(), ref_cnt.end(), 0);
    queue<int> q;
    q.push(B);
    visited[B] = true;
    while (!q.empty()) {
      const int cur = q.front();
      q.pop();
      for (int to : dag[cur]) {
        ref_cnt[to]++;
        if (!visited[to]) {
          q.push(to);
          visited[to] = true;
        }
      }
    }
    q.push(B);
    while (!q.empty()) {
      const int cur = q.front();
      ord.push_back(cur);
      q.pop();
      for (int to : dag[cur]) {
        if (--ref_cnt[to] == 0) {
          q.push(to);
        }
      }
    }
  }

  // Determine reachability for each query
  array<Flag, 100000> reachable;
  array<int, 128> dest;
  for (int i = 0; i < Q;) {
    for (auto &f : reachable) {
      f.reset();
    }
    int cnt = 0;
    for (int j = 0; j < 128 && i < Q; ++i, ++j) {
      int c, d;
      cin >> c >> d;
      --c;
      --d;
      reachable[d][j] = true;
      dest[j] = c;
      ++cnt;
    }
    for (int v : ord) {
      for (int next : dag[v]) {
        reachable[next] |= reachable[v];
      }
    }
    for (int j = 0; j < cnt; ++j) {
      if (reachable[dest[j]][j]) {
        cout << "Yes" << endl;
      } else {
        cout << "No" << endl;
      }
    }
  }
  return true;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(0);

  while (solve())
    ;
  return 0;
}

Error: -11

Fixed submission:

// Name: Railroad
// Level: 4
// Category: グラフ,Graph,最短経路,DAG
// Note:

/**
 * AからBまでの最短経路をDijkstra法で求め、そのときに使った辺のみから
 * なるDAGを構成する。
 * すると、cからdに最短経路で行けるかの判定は、このDAG上でcからdに行けるかの
 * 判定と等価になる。
 * 1クエリについて最悪全ノードの探索が必要で、これはO(N+M)になるが、
 * 到達可能かどうかは1bitしか使わないのでbit parallelで高速化ができる。
 * (N+M) × Q = 10^10 程度なので、数十倍程度の高速化をすれば制限時間に間に合う。
 *
 * オーダーは O(N log R + (N+M)Q)。
 */
#include <algorithm>
#include <array>
#include <bitset>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef bitset<192> Flag;
const LL INF = 100000LL * 1000 * 10;

bool solve() {
  int S, R;
  if (!(cin >> S >> R))
    return false;
  if (!S && !R)
    return false;

  array<vector<pair<int, LL>>, 100000> graph;
  array<vector<int>, 100000> dag;
  for (int i = 0; i < R; ++i) {
    int u, v, w;
    cin >> u >> v >> w;
    --u;
    --v;
    graph[u].push_back(make_pair(v, w));
    graph[v].push_back(make_pair(u, w));
  }
  int A, B, Q;
  cin >> A >> B >> Q;
  --A;
  --B;

  // Find shortest path
  array<LL, 100000> memo;
  priority_queue<pair<LL, int>> q;
  LL best_cost = INF;
  fill(memo.begin(), memo.end(), INF);
  q.push(make_pair(0, A));
  memo[A] = 0;
  while (!q.empty()) {
    const LL cost = -q.top().first;
    const int cur = q.top().second;
    q.pop();
    if (cost > best_cost)
      break;
    if (cur == B && best_cost == INF) {
      best_cost = cost;
    }
    if (memo[cur] < cost)
      continue;
    for (const auto &next : graph[cur]) {
      const LL nc = cost + next.second;
      if (nc < memo[next.first]) {
        dag[next.first].clear();
        dag[next.first].push_back(cur);
        memo[next.first] = nc;
        q.push(make_pair(-nc, next.first));
      } else if (memo[next.first] == nc) {
        dag[next.first].push_back(cur);
      }
    }
  }

  array<int, 100000> ref_cnt;
  {
    array<bool, 100000> visited;
    fill(visited.begin(), visited.end(), false);
    fill(ref_cnt.begin(), ref_cnt.end(), 0);
    queue<int> q;
    q.push(B);
    visited[B] = true;
    while (!q.empty()) {
      const int cur = q.front();
      q.pop();
      for (int to : dag[cur]) {
        ref_cnt[to]++;
        if (!visited[to]) {
          q.push(to);
          visited[to] = true;
        }
      }
    }
  }

  // Determine reachability for each query
  array<Flag, 100000> reachable;
  array<int, 192> dest;
  for (int i = 0; i < Q;) {
    for (auto &f : reachable) {
      f.reset();
    }
    int cnt = 0;
    for (int j = 0; j < 192 && i < Q; ++i, ++j) {
      int c, d;
      cin >> c >> d;
      --c;
      --d;
      reachable[d][j] = true;
      dest[j] = c;
      ++cnt;
    }
    auto rem_cnt = ref_cnt;
    queue<int> q;
    q.push(B);
    while (!q.empty()) {
      const int cur = q.front();
      q.pop();
      for (int next : dag[cur]) {
        reachable[next] |= reachable[cur];
        if (--rem_cnt[next] == 0) {
          q.push(next);
        }
      }
    }
    for (int j = 0; j < cnt; ++j) {
      if (reachable[dest[j]][j]) {
        cout << "Yes" << endl;
      } else {
        cout << "No" << endl;
      }
    }
  }
  return true;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(0);

  while (solve())
    ;
  return 0;
}