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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <limits.h>
#include <map>
#include <queue>
#include <set>
#include <string.h>
#include <vector>

using namespace std;
typedef long long ll;

const int MAX_N = 52;

struct Edge {
  int to;
  ll cost;
  ll time;

  Edge(int to = -1, int cost = -1, ll time = -1) {
    this->to = to;
    this->cost = cost;
    this->time = time;
  }
};

vector<Edge> E[MAX_N];

struct Node {
  int v;
  ll coin;
  ll time;

  Node(int v = -1, ll coin = -1, ll time = -1) {
    this->v = v;
    this->coin = coin;
    this->time = time;
  }

  bool operator>(const Node &n) const { return time > n.time; }
};

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

  ll u, v, a, b;
  for (int i = 0; i < M; ++i) {
    cin >> u >> v >> a >> b;

    E[u].push_back(Edge(v, a, b));
    E[v].push_back(Edge(u, a, b));
  }

  ll ans[N + 1];
  ll changeRate[N + 1];
  ll changeTime[N + 1];
  ll c, d;
  for (int i = 1; i <= N; ++i) {
    cin >> c >> d;

    ans[i] = LLONG_MAX;
    changeRate[i] = c;
    changeTime[i] = d;
  }

  ll LIMIT = N * 100;

  priority_queue<Node, vector<Node>, greater<Node>> pque;
  pque.push(Node(1, min(LIMIT, S), 0));

  ll minCoins[N + 1][LIMIT + 1];
  bool visited[N + 1][LIMIT + 1];
  memset(visited, false, sizeof(visited));
  int cnt = 0;

  for (int i = 0; i <= N; ++i) {
    for (int j = 0; j <= LIMIT; ++j) {
      minCoins[i][j] = LLONG_MAX;
    }
  }

  while (!pque.empty()) {
    Node node = pque.top();
    pque.pop();

    if (visited[node.v][node.coin])
      continue;
    visited[node.v][node.coin] = true;

    if (ans[node.v] > node.time) {
      fprintf(stderr, "%d: v: %d, coin: %lld, time: %lld\\n", ++cnt, node.v,
              node.coin, node.time);
    }

    ans[node.v] = min(ans[node.v], node.time);

    for (int i = 0; i < E[node.v].size(); ++i) {
      Edge edge = E[node.v][i];

      if (node.coin < edge.cost)
        continue;
      if (visited[edge.to][node.coin - edge.cost])
        continue;
      // visited[edge.to][node.coin - edge.cost] = true;
      if (minCoins[edge.to][node.coin - edge.cost] <= node.time + edge.time)
        continue;
      minCoins[edge.to][node.coin - edge.cost] = node.time + edge.time;

      pque.push(Node(edge.to, node.coin - edge.cost, node.time + edge.time));
    }

    while (node.coin < LIMIT) {
      node.coin += changeRate[node.v];
      node.coin = min(LIMIT, node.coin);
      node.time += changeTime[node.v];

      if (visited[node.v][node.coin])
        break;
      // visited[node.v][node.coin] = true;
      if (minCoins[node.v][node.coin] <= node.time)
        break;
      minCoins[node.v][node.coin] = node.time;

      pque.push(node);
    }
  }

  for (int t = 2; t <= N; ++t) {
    cout << ans[t] << endl;
  }

  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <limits.h>
#include <map>
#include <queue>
#include <set>
#include <string.h>
#include <vector>

using namespace std;
typedef long long ll;

const int MAX_N = 52;

struct Edge {
  int to;
  ll cost;
  ll time;

  Edge(int to = -1, int cost = -1, ll time = -1) {
    this->to = to;
    this->cost = cost;
    this->time = time;
  }
};

vector<Edge> E[MAX_N];

struct Node {
  int v;
  ll coin;
  ll time;

  Node(int v = -1, ll coin = -1, ll time = -1) {
    this->v = v;
    this->coin = coin;
    this->time = time;
  }

  bool operator>(const Node &n) const { return time > n.time; }
};

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

  ll u, v, a, b;
  for (int i = 0; i < M; ++i) {
    cin >> u >> v >> a >> b;

    E[u].push_back(Edge(v, a, b));
    E[v].push_back(Edge(u, a, b));
  }

  ll ans[N + 1];
  ll changeRate[N + 1];
  ll changeTime[N + 1];
  ll c, d;
  for (int i = 1; i <= N; ++i) {
    cin >> c >> d;

    ans[i] = LLONG_MAX;
    changeRate[i] = c;
    changeTime[i] = d;
  }

  ll LIMIT = 5000;

  priority_queue<Node, vector<Node>, greater<Node>> pque;
  pque.push(Node(1, min(LIMIT, S), 0));

  ll minCoins[N + 1][LIMIT + 1];
  bool visited[N + 1][LIMIT + 1];
  memset(visited, false, sizeof(visited));
  int cnt = 0;

  for (int i = 0; i <= N; ++i) {
    for (int j = 0; j <= LIMIT; ++j) {
      minCoins[i][j] = LLONG_MAX;
    }
  }

  while (!pque.empty()) {
    Node node = pque.top();
    pque.pop();

    if (visited[node.v][node.coin])
      continue;
    visited[node.v][node.coin] = true;

    if (ans[node.v] > node.time) {
      fprintf(stderr, "%d: v: %d, coin: %lld, time: %lld\\n", ++cnt, node.v,
              node.coin, node.time);
    }

    ans[node.v] = min(ans[node.v], node.time);

    for (int i = 0; i < E[node.v].size(); ++i) {
      Edge edge = E[node.v][i];

      if (node.coin < edge.cost)
        continue;
      if (visited[edge.to][node.coin - edge.cost])
        continue;
      // visited[edge.to][node.coin - edge.cost] = true;
      if (minCoins[edge.to][node.coin - edge.cost] <= node.time + edge.time)
        continue;
      minCoins[edge.to][node.coin - edge.cost] = node.time + edge.time;

      pque.push(Node(edge.to, node.coin - edge.cost, node.time + edge.time));
    }

    while (node.coin < LIMIT) {
      node.coin += changeRate[node.v];
      node.coin = min(LIMIT, node.coin);
      node.time += changeTime[node.v];

      if (visited[node.v][node.coin])
        break;
      // visited[node.v][node.coin] = true;
      if (minCoins[node.v][node.coin] <= node.time)
        break;
      minCoins[node.v][node.coin] = node.time;

      pque.push(node);
    }
  }

  for (int t = 2; t <= N; ++t) {
    cout << ans[t] << endl;
  }

  return 0;
}