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

#include <algorithm>
#include <cstring>
#include <functional>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

const int INF = 1e9 + 10;

struct Edge {
  int to, dist, constraint;

  Edge() = default;
  Edge(int t, int d, int c) : to(t), dist(d), constraint(c) {}
};

struct Node {
  double cost;
  int cur, prev, v;

  Node() = default;
  Node(double c, int cur, int prev, int v)
      : cost(c), cur(cur), prev(prev), v(v) {}

  inline bool operator<(const Node &node) const { return cost < node.cost; }

  inline bool operator>(const Node &node) const { return cost > node.cost; }
};

int main() {
  while (true) {
    int n, m;
    cin >> n >> m;
    if (n + m == 0) {
      break;
    }
    int s, g;
    cin >> s >> g;

    vector<Edge> G[31];
    for (int i = 0; i < m; i++) {
      int x, y, d, c;
      cin >> x >> y >> d >> c;
      G[x].push_back(Edge(y, d, c));
      G[y].push_back(Edge(x, d, c));
    }

    double min_cost[31][31][31];
    for (int i = 0; i < 31; i++) {
      for (int j = 0; j < 31; j++) {
        for (int k = 0; k < 31; k++) {
          min_cost[i][j][k] = INF;
        }
      }
    }

    priority_queue<Node, vector<Node>, greater<Node>> que;
    min_cost[s][0][1] = 0;
    que.push(Node(0, s, -1, 0));

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

      for (const auto &e : G[node.cur]) {
        if (node.prev == e.to) {
          continue;
        }
        const int dv[3] = {-1, 0, 1};
        for (int i = 0; i < 3; i++) {
          int nv = node.v + dv[i];
          if (nv > 0 && nv <= e.constraint) {
            double temp = e.dist / (double)nv;
            if (min_cost[e.to][node.cur][nv] > node.cost + temp) {
              min_cost[e.to][node.cur][nv] = node.cost + temp;
              que.push(Node(node.cost + temp, e.to, node.cur, nv));
            }
          }
        }
      }
    }

    double ans = INF;
    for (int i = 1; i <= n; i++) {
      ans = min(ans, min_cost[g][i][1]);
    }
    if (ans >= INF) {
      cout << "unreachable" << endl;
    } else {
      printf("%.15f\\n", ans);
    }
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

const int INF = 1e9 + 10;

struct Edge {
  int to, dist, constraint;

  Edge() = default;
  Edge(int t, int d, int c) : to(t), dist(d), constraint(c) {}
};

struct Node {
  double cost;
  int cur, prev, v;

  Node() = default;
  Node(double c, int cur, int prev, int v)
      : cost(c), cur(cur), prev(prev), v(v) {}

  inline bool operator<(const Node &node) const { return cost < node.cost; }
};

int main() {
  while (true) {
    int n, m;
    cin >> n >> m;
    if (n + m == 0) {
      break;
    }
    int s, g;
    cin >> s >> g;

    vector<Edge> G[31];
    for (int i = 0; i < m; i++) {
      int x, y, d, c;
      cin >> x >> y >> d >> c;
      G[x].push_back(Edge(y, d, c));
      G[y].push_back(Edge(x, d, c));
    }

    double min_cost[31][31][31];
    for (int i = 0; i < 31; i++) {
      for (int j = 0; j < 31; j++) {
        for (int k = 0; k < 31; k++) {
          min_cost[i][j][k] = INF;
        }
      }
    }

    priority_queue<Node> que;
    que.push(Node(0, s, -1, 1));

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

      min_cost[node.cur][node.prev][node.v] = node.cost;

      for (const auto &e : G[node.cur]) {
        if (node.prev == e.to) {
          continue;
        }
        double temp = e.dist / (double)(node.v);
        if (min_cost[e.to][node.cur][node.v] > node.cost + temp) {
          que.push(Node(node.cost + temp, e.to, node.cur, node.v));
        }
        if (node.prev != -1) {
          if (node.v < e.constraint) {
            temp = e.dist / (double)(node.v + 1);
            if (min_cost[e.to][node.cur][node.v + 1] > node.cost + temp) {
              que.push(Node(node.cost + temp, e.to, node.cur, node.v + 1));
            }
          }
          if (node.v > 1) {
            temp = e.dist / (double)(node.v - 1);
            if (min_cost[e.to][node.cur][node.v - 1] > node.cost + temp) {
              que.push(Node(node.cost + temp, e.to, node.cur, node.v - 1));
            }
          }
        }

        if (e.to == g && node.v == 1) {
          min_cost[g][node.cur][1] =
              min(min_cost[g][node.cur][1], node.cost + e.dist);
        }
      }
    }

    double ans = INF;
    for (int i = 1; i <= n; i++) {
      ans = min(ans, min_cost[g][i][1]);
    }
    if (ans >= INF) {
      cout << "unreachable" << endl;
    } else {
      printf("%.15f\\n", ans);
    }
  }

  return 0;
}