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

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using vi = vector<int>;
using vvi = vector<vi>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vl = vector<ll>;
using vvl = vector<vl>;
using vd = vector<double>;
using vvd = vector<vd>;

#define REP(i, n) for (ll i = 0; i < (n); ++i)
#define ALL(c) (c).begin(), (c).end()
#define FOR(i, s, e) for (ll i = s; i < (ll)e; i++)
#define TEN(x) ((ll)1e##x)

template <class Edge, class State> struct dijkstra {
  using Cost = decltype(State{}.calc_cost(Edge{}));

  static vector<Cost> shortest_path(State s, const vector<vector<Edge>> &g,
                                    Cost max_dist) {
    vector<Cost> d(State::max_state_id() + 1, max_dist);
    d[s.state_id()] = 0;
    using P = pair<ll, State>;
    priority_queue<P, vector<P>, greater<P>> que;
    que.push(P(0, s));
    while (!que.empty()) {
      Cost cur_d;
      State cur;
      tie(cur_d, cur) = que.top();
      que.pop();
      auto v = cur.state_id();
      if (d[v] < cur_d)
        continue;
      for (auto e : g[cur.node_id])
        if (cur.is_valid(e)) {
          State next = cur.calc_next(e);
          auto u = next.state_id();
          if (d[u] > d[v] + cur.calc_cost(e)) {
            d[u] = d[v] + cur.calc_cost(e);
            que.push(P(d[u], next));
          }
        }
    }

    return d;
  }
};

vector<vvl> dist;
void warshall_floyd(ll c) { // cost[n][n]
  int n = dist[c].size();
  REP(k, n)
  REP(i, n) REP(j, n) dist[c][i][j] =
      min(dist[c][i][j], dist[c][i][k] + dist[c][k][j]);
}

vvl pay;
struct Edge {
  ll to, c;
};
struct State {
  static ll max_state_id() { return TEN(5) * 5 + 1; }
  bool operator<(const State &rhs) const {
    if (node_id != rhs.node_id)
      return node_id < rhs.node_id;
    if (c != rhs.c)
      return c < rhs.c;
    return start_id < rhs.start_id;
  }

  ll node_id;

  // more infomation
  ll c, start_id;

  ll state_id() { return node_id + c * 100 + start_id * 100 * 20; }
  bool is_valid(Edge e) {
    ll id = (e.c == c ? this->start_id : node_id);
    return pay[e.c][dist[e.c][id][e.to]] >= pay[e.c][dist[e.c][id][node_id]];
  }
  State calc_next(Edge e) {
    return State{e.to, e.c, (e.c == c ? start_id : node_id)};
  }
  ll calc_cost(Edge e) {
    ll id = (e.c == c ? this->start_id : node_id);
    return pay[e.c][dist[e.c][id][e.to]] - pay[e.c][dist[e.c][id][node_id]];
  }
};

int main() {
#ifdef INPUT_FROM_FILE
  ifstream cin("sample.in");
  ofstream cout("sample.out");
#endif
  cin.tie(0);
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(50);

  while (true) {
    ll n, m, c, s, g;
    cin >> n >> m >> c >> s >> g;
    s--, g--;
    if (n == 0)
      break;

    vector<tuple<ll, ll, ll, ll>> paths(m);
    REP(i, m) {
      cin >> get<0>(paths[i]) >> get<1>(paths[i]) >> get<2>(paths[i]) >>
          get<3>(paths[i]);
      get<0>(paths[i])--, get<1>(paths[i])--, get<3>(paths[i])--;
    }

    ll max_d = TEN(6) * 4 + 1;

    {
      dist = vector<vvl>(c, vvl(n, vl(n, max_d)));
      REP(i, c) REP(j, n) dist[i][j][j] = 0;
      REP(i, m)
      if (dist[get<3>(paths[i])][get<0>(paths[i])][get<1>(paths[i])] >
          get<2>(paths[i])) {
        dist[get<3>(paths[i])][get<0>(paths[i])][get<1>(paths[i])] =
            get<2>(paths[i]);
        dist[get<3>(paths[i])][get<1>(paths[i])][get<0>(paths[i])] =
            get<2>(paths[i]);
      }
      REP(i, c) warshall_floyd(i);
    }

    {
      vl p(c);
      REP(i, c) cin >> p[i];

      vvl q(c), r(c);
      REP(i, c) {
        q[i].resize(p[i] - 1);
        r[i].resize(p[i]);
        REP(j, p[i] - 1) cin >> q[i][j];
        REP(j, p[i]) cin >> r[i][j];
      }

      pay = vvl(c);
      REP(i, c) {
        ll len = 0;
        REP(j, n)
        REP(k, n) if (dist[i][j][k] != max_d) len = max(len, dist[i][j][k]);

        pay[i].resize(len + 1);
        pay[i][0] = 0;
        FOR(j, 1, len + 1) {
          pay[i][j] =
              pay[i][j - 1] + r[i][lower_bound(ALL(q[i]), j) - q[i].begin()];
        }
      }
    }

    {
      vector<vector<Edge>> graph(n);
      REP(i, m) {
        graph[get<0>(paths[i])].push_back({get<1>(paths[i]), get<3>(paths[i])});
        graph[get<1>(paths[i])].push_back({get<0>(paths[i]), get<3>(paths[i])});
      }

      auto d =
          dijkstra<Edge, State>::shortest_path(State{s, 0, s}, graph, max_d);
      ll ans = max_d;
      REP(i, c) REP(j, n) ans = min<ll>(ans, d[State{g, i, j}.state_id()]);
      cout << (ans == max_d ? -1 : ans) << endl;
    }
  }

  return 0;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using vi = vector<int>;
using vvi = vector<vi>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vl = vector<ll>;
using vvl = vector<vl>;
using vd = vector<double>;
using vvd = vector<vd>;

#define REP(i, n) for (ll i = 0; i < (n); ++i)
#define ALL(c) (c).begin(), (c).end()
#define FOR(i, s, e) for (ll i = s; i < (ll)e; i++)
#define TEN(x) ((ll)1e##x)

template <class Edge, class State> struct dijkstra {
  using Cost = decltype(State{}.calc_cost(Edge{}));

  static vector<Cost> shortest_path(State s, const vector<vector<Edge>> &g,
                                    Cost max_dist) {
    vector<Cost> d(State::max_state_id() + 1, max_dist);
    d[s.state_id()] = 0;
    using P = pair<ll, State>;
    priority_queue<P, vector<P>, greater<P>> que;
    que.push(P(0, s));
    while (!que.empty()) {
      Cost cur_d;
      State cur;
      tie(cur_d, cur) = que.top();
      que.pop();
      auto v = cur.state_id();
      if (d[v] < cur_d)
        continue;
      for (auto e : g[cur.node_id])
        if (cur.is_valid(e)) {
          State next = cur.calc_next(e);
          auto u = next.state_id();
          if (d[u] > d[v] + cur.calc_cost(e)) {
            d[u] = d[v] + cur.calc_cost(e);
            que.push(P(d[u], next));
          }
        }
    }

    return d;
  }
};

vector<vvl> dist;
void warshall_floyd(ll c) { // cost[n][n]
  int n = dist[c].size();
  REP(k, n)
  REP(i, n) REP(j, n) dist[c][i][j] =
      min(dist[c][i][j], dist[c][i][k] + dist[c][k][j]);
}

vvl pay;
struct Edge {
  ll to, c;
};
struct State {
  static ll max_state_id() { return TEN(5) * 5 + 1; }
  bool operator<(const State &rhs) const {
    if (node_id != rhs.node_id)
      return node_id < rhs.node_id;
    if (c != rhs.c)
      return c < rhs.c;
    return start_id < rhs.start_id;
  }

  ll node_id;

  // more infomation
  ll c, start_id;

  ll state_id() { return node_id + c * 100 + start_id * 100 * 20; }
  bool is_valid(Edge e) {
    ll id = (e.c == c ? this->start_id : node_id);
    return pay[e.c][dist[e.c][id][e.to]] >= pay[e.c][dist[e.c][id][node_id]];
  }
  State calc_next(Edge e) {
    return State{e.to, e.c, (e.c == c ? start_id : node_id)};
  }
  ll calc_cost(Edge e) {
    ll id = (e.c == c ? this->start_id : node_id);
    return pay[e.c][dist[e.c][id][e.to]] - pay[e.c][dist[e.c][id][node_id]];
  }
};

int main() {
#ifdef INPUT_FROM_FILE
  ifstream cin("sample.in");
  ofstream cout("sample.out");
#endif
  cin.tie(0);
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(50);

  while (true) {
    ll n, m, c, s, g;
    cin >> n >> m >> c >> s >> g;
    s--, g--;
    if (n == 0)
      break;

    vector<tuple<ll, ll, ll, ll>> paths(m);
    REP(i, m) {
      cin >> get<0>(paths[i]) >> get<1>(paths[i]) >> get<2>(paths[i]) >>
          get<3>(paths[i]);
      get<0>(paths[i])--, get<1>(paths[i])--, get<3>(paths[i])--;
    }

    ll max_d = TEN(6);

    {
      vl p(c);
      REP(i, c) cin >> p[i];

      vvl q(c), r(c);
      REP(i, c) {
        q[i].resize(p[i] - 1);
        r[i].resize(p[i]);
        REP(j, p[i] - 1) cin >> q[i][j];
        REP(j, p[i]) cin >> r[i][j];
      }

      pay = vvl(c, vl(max_d + 1));
      REP(i, c) {
        pay[i][0] = 0;
        FOR(j, 1, max_d + 1) {
          pay[i][j] =
              pay[i][j - 1] + r[i][lower_bound(ALL(q[i]), j) - q[i].begin()];
        }
      }
    }

    {
      dist = vector<vvl>(c, vvl(n, vl(n, max_d)));
      REP(i, c) REP(j, n) dist[i][j][j] = 0;
      REP(i, m)
      if (dist[get<3>(paths[i])][get<0>(paths[i])][get<1>(paths[i])] >
          get<2>(paths[i])) {
        dist[get<3>(paths[i])][get<0>(paths[i])][get<1>(paths[i])] =
            get<2>(paths[i]);
        dist[get<3>(paths[i])][get<1>(paths[i])][get<0>(paths[i])] =
            get<2>(paths[i]);
      }
      REP(i, c) warshall_floyd(i);
    }

    {
      vector<vector<Edge>> graph(n);
      REP(i, m) {
        graph[get<0>(paths[i])].push_back({get<1>(paths[i]), get<3>(paths[i])});
        graph[get<1>(paths[i])].push_back({get<0>(paths[i]), get<3>(paths[i])});
      }

      auto d =
          dijkstra<Edge, State>::shortest_path(State{s, 0, s}, graph, max_d);
      ll ans = max_d;
      REP(i, c) REP(j, n) ans = min<ll>(ans, d[State{g, i, j}.state_id()]);
      cout << (ans == max_d ? -1 : ans) << endl;
    }
  }

  return 0;
}