Problem p02703 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdint>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define N_TIMES(i, n) for (uint64_t i = 0; i < n; ++i)
#define N_TIMES_REV(i, n) for (int64_t i = n - 1; i >= 0; --i)

using namespace std;

const uint64_t INF = 1e+18;

struct Edge {
  uint64_t A, B;
  Edge(uint64_t A = INF, uint64_t B = INF) : A(A), B(B) {}
};

istream &operator>>(istream &is, Edge &edge) {
  is >> edge.A >> edge.B;
  return is;
}

struct Exchange {
  uint64_t C, D;
  Exchange(uint64_t C = INF, uint64_t D = INF) : C(C), D(D) {}
  long double rate() const {
    return static_cast<long double>(C) / static_cast<long double>(D);
  }
  bool operator<(const Exchange &ex) const { return C * ex.D < D * ex.C; }
};

istream &operator>>(istream &is, Exchange &exchange) {
  is >> exchange.C >> exchange.D;
  return is;
}

struct SearchItem {
  uint64_t pos, silver, time;
  SearchItem(uint64_t pos, uint64_t silver, uint64_t time)
      : pos(pos), silver(silver), time(time) {}
  bool operator<(const SearchItem &item) const { return time > item.time; }
};

int main() {
  uint64_t N, M, S;
  cin >> N >> M >> S;

  uint64_t A_max = 0;
  vector<vector<Edge>> edges(N, vector<Edge>(N));
  N_TIMES(m, M) {
    uint64_t U, V;
    Edge E;

    cin >> U >> V >> E;
    --U;
    --V;
    edges[U][V] = E;
    edges[V][U] = E;
    A_max = max(A_max, E.A);
  }

  vector<Exchange> exchanges(N);
  N_TIMES(n, N) { cin >> exchanges[n]; }

  vector<vector<uint64_t>> times(N, vector<uint64_t>(A_max * N, INF));
  if (S > A_max * N) {
    S = A_max * N - 1;
  }
  times[0][S] = 0;

  priority_queue<SearchItem> q;
  q.emplace(0, S, 0);

  while (!q.empty()) {
    SearchItem item = q.top();
    q.pop();
    if (item.time == INF) {
      continue;
    }

    // 移動
    N_TIMES(v, N) {
      Edge edge = edges[item.pos][v];
      // 線路があり，かつ運賃を支払える
      if ((edge.B != INF) && (edge.A <= item.silver)) {
        SearchItem new_item(v, item.silver - edge.A, item.time + edge.B);
        if (new_item.time < times[new_item.pos][new_item.silver]) {
          times[new_item.pos][new_item.silver] = new_item.time;
          q.push(new_item);
        }
      }
    }

    // 両替
    Exchange exchange = exchanges[item.pos];
    if (item.silver + exchange.C < A_max * N) {
      SearchItem new_item(item.pos, item.silver + exchange.C,
                          item.time + exchange.D);
      if (new_item.time < times[new_item.pos][new_item.silver]) {
        times[new_item.pos][new_item.silver] = new_item.time;
        q.push(new_item);
      }
    }
  }

  for (uint64_t n = 1; n < N; ++n) {
    uint64_t ans = INF;
    N_TIMES(s, A_max * N) { ans = min(ans, times[n][s]); }
    cout << ans << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdint>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define N_TIMES(i, n) for (uint64_t i = 0; i < n; ++i)
#define N_TIMES_REV(i, n) for (int64_t i = n - 1; i >= 0; --i)

using namespace std;

const uint64_t INF = 1e+18; // static_cast<uint64_t>(-1);

struct Edge {
  uint64_t A, B;
  Edge(uint64_t A = INF, uint64_t B = INF) : A(A), B(B) {}
};

istream &operator>>(istream &is, Edge &edge) {
  is >> edge.A >> edge.B;
  return is;
}

struct Exchange {
  uint64_t C, D;
  Exchange(uint64_t C = INF, uint64_t D = INF) : C(C), D(D) {}
  long double rate() const {
    return static_cast<long double>(C) / static_cast<long double>(D);
  }
  bool operator<(const Exchange &ex) const { return C * ex.D < D * ex.C; }
};

istream &operator>>(istream &is, Exchange &exchange) {
  is >> exchange.C >> exchange.D;
  return is;
}

struct SearchItem {
  uint64_t pos, silver, time;
  SearchItem(uint64_t pos, uint64_t silver, uint64_t time)
      : pos(pos), silver(silver), time(time) {}
  bool operator<(const SearchItem &item) const { return time < item.time; }
};

int main() {
  uint64_t N, M, S;
  cin >> N >> M >> S;

  uint64_t A_max = 0;
  vector<vector<Edge>> edges(N, vector<Edge>(N));
  N_TIMES(m, M) {
    uint64_t U, V;
    Edge E;

    cin >> U >> V >> E;
    --U;
    --V;
    edges[U][V] = E;
    edges[V][U] = E;
    A_max = max(A_max, E.A);
  }

  vector<Exchange> exchanges(N);
  N_TIMES(n, N) { cin >> exchanges[n]; }

  vector<vector<uint64_t>> times(N, vector<uint64_t>(A_max * N, INF));
  if (S > A_max * N) {
    S = A_max * N - 1;
  }
  times[0][S] = 0;

  priority_queue<SearchItem> q;
  q.emplace(0, S, 0);

  while (!q.empty()) {
    SearchItem item = q.top();
    q.pop();
    if (item.time == INF) {
      continue;
    }

    // 移動
    N_TIMES(v, N) {
      Edge edge = edges[item.pos][v];
      // 線路があり，かつ運賃を支払える
      if ((edge.B != INF) && (edge.A <= item.silver)) {
        SearchItem new_item(v, item.silver - edge.A, item.time + edge.B);
        if (new_item.time < times[new_item.pos][new_item.silver]) {
          times[new_item.pos][new_item.silver] = new_item.time;
          q.push(new_item);
        }
      }
    }

    // 両替
    Exchange exchange = exchanges[item.pos];
    if (item.silver + exchange.C < A_max * N) {
      SearchItem new_item(item.pos, item.silver + exchange.C,
                          item.time + exchange.D);
      if (new_item.time < times[new_item.pos][new_item.silver]) {
        times[new_item.pos][new_item.silver] = new_item.time;
        q.push(new_item);
      }
    }
  }

  for (uint64_t n = 1; n < N; ++n) {
    uint64_t ans = 1e+18;
    N_TIMES(s, A_max * N) { ans = min(ans, times[n][s]); }
    cout << ans << endl;
  }

  return 0;
}