Problem p02949 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bits/stdc++.h>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <sstream>
#include <string>
#include <vector>

using namespace std;
#define REP(i, n) FOR(i, 0, n)
#define FOR(i, sta, n)                                                         \
  for (long long i = (sta), i##Len_ = (n); i < i##Len_; i++)
typedef long long ll;
static const ll MOD = 1000000007;
// static const ll INF = 1000000000000000000LL;
const ll mod = 998244353;
const ll INF = mod * mod;

struct edge {
  int to;
  ll cost;
};

const int em_max = 2500;

vector<edge> G[em_max];
vector<int> rG[em_max];

ll score[em_max];

bool canGoal[em_max];
bool canStart[em_max];

// 最短経路問題
// 負の辺がでてくる
int main() {
  ll N, M, P;
  cin >> N >> M >> P;

  REP(i, N) {
    // edge:a->b; cost:c
    int a, b, c;
    cin >> a >> b >> c;
    --a;
    --b;
    G[a].push_back({b, c});
    rG[b].push_back(a);
  }
  // 初期化
  std::fill(score, score + N, -INF);
  score[0] = 0;

  // 0 -> N-1
  queue<int> q;
  q.push(N - 1);
  canGoal[N - 1] = true;
  while (!q.empty()) {
    int id = q.front();
    q.pop();
    REP(j, rG[id].size()) {
      int to = rG[id][j];
      // すでにゴールに到達できることがわかっている
      if (canGoal[to])
        continue;
      canGoal[to] = true;
      q.push(to);
    }
  }

  // q.empty() == true

  q.push(0);
  canStart[0] = true;
  while (!q.empty()) {
    int id = q.front();
    q.pop();
    REP(j, G[id].size()) {
      int to = G[id][j].to;
      if (canStart[to])
        continue;
      canStart[to] = true;
      q.push(to);
    }
  }

  REP(i, N) {
    if (canStart[i] == false) {
      canGoal[i] = false;
    }
  }

  REP(t, 5000) {
    REP(i, N) {
      if (canGoal[i] == false)
        continue;
      REP(j, G[i].size()) {
        int to = G[i][j].to;
        if (canGoal[to] == false)
          continue;
        // 1辺の移動のたびに -P される
        ll ns = score[i] + G[i][j].cost - P;
        if (score[to] < ns) {
          score[to] = ns;
        }
      }
    }
  }

  // まだ最大値が更新されるなら、存在しない
  REP(i, N) {
    if (canGoal[i] == false)
      continue;
    REP(j, G[i].size()) {
      int to = G[i][j].to;
      if (canGoal[to] == false)
        continue;
      // 1辺の移動のたびに -P される
      ll ns = score[i] + G[i][j].cost - P;
      if (score[to] < ns) {
        score[to] = ns;

        cout << -1 << endl;
        return 0;
      }
    }
  }

  if (score[N - 1] < 0)
    score[N - 1] = 0;
  cout << score[N - 1] << endl;

  return 0;
}

Fixed submission:
#include <algorithm>
#include <bits/stdc++.h>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <sstream>
#include <string>
#include <vector>

using namespace std;
#define REP(i, n) FOR(i, 0, n)
#define FOR(i, sta, n)                                                         \
  for (long long i = (sta), i##Len_ = (n); i < i##Len_; i++)
typedef long long ll;
static const ll MOD = 1000000007;
// static const ll INF = 1000000000000000000LL;
const ll mod = 998244353;
const ll INF = mod * mod;

struct edge {
  int to;
  ll cost;
};

const int em_max = 2500;

vector<edge> G[em_max];
vector<int> rG[em_max];

ll score[em_max];

bool canGoal[em_max];
bool canStart[em_max];

// 最短経路問題
// 負の辺がでてくる
int main() {
  ll N, M, P;
  cin >> N >> M >> P;
  REP(i, M) {
    // edge:a->b; cost:c
    int a, b, c;
    cin >> a >> b >> c;
    --a;
    --b;
    G[a].push_back({b, c});
    rG[b].push_back(a);
  }
  // 初期化
  std::fill(score, score + N, -INF);
  score[0] = 0;

  // 0 -> N-1
  queue<int> q;
  q.push(N - 1);
  canGoal[N - 1] = true;
  while (!q.empty()) {
    int id = q.front();
    q.pop();
    REP(j, rG[id].size()) {
      int to = rG[id][j];
      // すでにゴールに到達できることがわかっている
      if (canGoal[to])
        continue;
      canGoal[to] = true;
      q.push(to);
    }
  }

  // q.empty() == true

  q.push(0);
  canStart[0] = true;
  while (!q.empty()) {
    int id = q.front();
    q.pop();
    REP(j, G[id].size()) {
      int to = G[id][j].to;
      if (canStart[to])
        continue;
      canStart[to] = true;
      q.push(to);
    }
  }

  REP(i, N) {
    if (canStart[i] == false) {
      canGoal[i] = false;
    }
  }

  REP(t, 5000) {
    REP(i, N) {
      if (canGoal[i] == false)
        continue;
      REP(j, G[i].size()) {
        int to = G[i][j].to;
        if (canGoal[to] == false)
          continue;
        // 1辺の移動のたびに -P される
        ll ns = score[i] + G[i][j].cost - P;
        if (score[to] < ns) {
          score[to] = ns;
        }
      }
    }
  }

  // まだ最大値が更新されるなら、存在しない
  REP(i, N) {
    if (canGoal[i] == false)
      continue;
    REP(j, G[i].size()) {
      int to = G[i][j].to;
      if (canGoal[to] == false)
        continue;
      // 1辺の移動のたびに -P される
      ll ns = score[i] + G[i][j].cost - P;
      if (score[to] < ns) {
        score[to] = ns;

        cout << -1 << endl;
        return 0;
      }
    }
  }

  if (score[N - 1] < 0)
    score[N - 1] = 0;
  cout << score[N - 1] << endl;

  return 0;
}