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

#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
using namespace std;

struct edge {
  int to, cost;
  edge(int to_, int cost_) {
    to = to_;
    cost = cost_;
  }
};
const int MAX_N = 101;
const int MAX_M = 1001;
const int INF = 1e+8;
vector<edge> G[MAX_N];
// memo[k][v] := 頂点 v までたどり着くのに k 回エッジのコストを 0
// にした状態を探索したかどうか.
bool memo[MAX_M][MAX_N];
int n, m, c;

struct State {
  // cost := コスト, e := エッジのコストを変更した回数, v := 頂点
  int cost, e, v;
  State(int cost_, int e_, int v_) {
    cost = cost_;
    e = e_;
    v = v_;
  }
};
bool operator<(const State &a, const State &b) { return a.cost > b.cost; }

int solve() {
  for (int i = 0; i < MAX_M; i++)
    fill(memo[i], memo[i] + MAX_N, false);

  priority_queue<State> q;
  q.push(State(0, 0, 0));
  int res = INF;
  while (!q.empty()) {
    int cost = q.top().cost, e = q.top().e, v = q.top().v;
    q.pop();

    if (memo[e][v])
      continue;
    memo[e][v] = true;

    if (v == n - 1) { // ゴールの時
      res = min(res, e);
      continue;
    }

    for (int i = 0; i < G[v].size(); i++) {
      int to = G[v][i].to;
      int next_cost = cost + G[v][i].cost;

      if (!memo[e][to] && next_cost <= c) { // エッジのコストを変更しない
        q.push(State(next_cost, e, to));
      }
      next_cost -= G[v][i].cost;
      if (!memo[e + 1][to] && e + 1 <= n) { // エッジのコストを変更する
        q.push(State(next_cost, e + 1, to));
      }
    }
  }
  return res;
}

void add_edge(int u, int v, int cost) { G[u].push_back(edge(v, cost)); }

int main() {
  while (cin >> n >> m >> c, n || m || c) {
    for (int i = 0; i < MAX_N; i++)
      G[i].clear();

    for (int i = 0; i < m; i++) {
      int u, v, cost;
      cin >> u >> v >> cost;
      u--;
      v--;
      add_edge(u, v, cost);
    }
    cout << solve() << endl;
  }
}

Error: 0

Fixed submission:

#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
using namespace std;

struct edge {
  int to, cost;
  edge(int to_, int cost_) {
    to = to_;
    cost = cost_;
  }
};
const int MAX_N = 101;
const int MAX_M = 1001;
const int INF = 1e+8;
vector<edge> G[MAX_N];
// dp[k][v] := 頂点 v までたどり着くときにエッジを k 回コストを 0
// にしたときの最小コスト
int dp[MAX_M][MAX_N];
int n, m, c;

struct State {
  int cost, e, v;
  State(int cost_, int e_, int v_) {
    cost = cost_;
    e = e_;
    v = v_;
  }
};
bool operator<(const State &a, const State &b) { return a.cost > b.cost; }

int solve() {
  for (int i = 0; i < MAX_M; i++)
    fill(dp[i], dp[i] + MAX_N, INF);

  dp[0][0] = 0;
  priority_queue<State> q;
  q.push(State(0, 0, 0));
  while (!q.empty()) {
    int cost = q.top().cost, e = q.top().e, v = q.top().v;
    q.pop();

    for (int i = 0; i < G[v].size(); i++) {
      int to = G[v][i].to;
      int next_cost = cost + G[v][i].cost;

      if (next_cost < dp[e][to]) {
        dp[e][to] = next_cost;
        q.push(State(next_cost, e, to));
      }
      next_cost -= G[v][i].cost;
      if (next_cost < dp[e + 1][to]) {
        dp[e + 1][to] = next_cost;
        q.push(State(next_cost, e + 1, to));
      }
    }
  }
  for (int i = 0; i < MAX_M; i++) {
    if (dp[i][n - 1] <= c)
      return i;
  }
  return 0;
}

void add_edge(int u, int v, int cost) { G[u].push_back(edge(v, cost)); }

int main() {
  while (cin >> n >> m >> c, n || m || c) {
    for (int i = 0; i < MAX_N; i++)
      G[i].clear();

    for (int i = 0; i < m; i++) {
      int u, v, cost;
      cin >> u >> v >> cost;
      u--;
      v--;
      add_edge(u, v, cost);
    }
    cout << solve() << endl;
  }
}