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


#include <cfloat>
#include <iostream>
#include <queue>

using namespace std;

class State {
public:
  double _time; // ©©Á½Ô
  int _speed;   // ¬x
  int _town;    // »Ýn
  int _utern;   // OñÌ¬it^[Ö~j
  State(double time, int speed, int town, int utern)
      : _time(time), _speed(speed), _town(town), _utern(utern) {}
  bool operator<(const State &tmp) const { return _time > tmp._time; }
};

class Edge {
public:
  int _d; // £
  int _c; // §À¬x
  Edge() {}
  Edge(int d, int c) : _d(d), _c(c) {}
};

int main() {
  for (;;) {
    // Init
    int n, m, s, g;
    cin >> n >> m;
    if (n == 0 && m == 0)
      break;

    cin >> s >> g;
    --s;
    --g;

    Edge *Graph[30][30];
    for (int i = 0; i < 30; i++) {
      for (int j = 0; j < 30; j++) {
        Graph[i][j] = NULL;
      }
    }

    for (int i = 0; i < m; i++) {
      int x, y, d, c;
      cin >> x >> y >> d >> c;
      --x;
      --y;
      Graph[x][y] = new Edge(d, c);
      Graph[y][x] = new Edge(d, c);
    }

    bool Visited[30][30][30]; // »Ýn@t^[Ö~@¬x
    double Cost[30][30][30];
    for (int i = 0; i < 30; i++) {
      for (int j = 0; j < 30; j++) {
        for (int k = 0; k < 30; k++) {
          Visited[i][j][k] = false;
          Cost[i][j][k] = DBL_MAX;
        }
      }
    }

    priority_queue<State> PQ;
    PQ.push(State(0.0, 0, s, s));
    Cost[s][s][0] = 0;

    double min_time = -1;

    // Dijkstra
    while (!PQ.empty()) {
      State tmp = PQ.top();
      PQ.pop();
      if (Visited[tmp._town][tmp._utern][tmp._speed] == true)
        continue;
      // cout << "time " << tmp._time << " town "<< tmp._town+1 << " speed " <<
      // tmp._speed << endl;
      if (tmp._town == g && tmp._speed == 1) {
        min_time = tmp._time;
        break;
      }
      Visited[tmp._town][tmp._utern][tmp._speed] = true;

      for (int i = 0; i < n; i++) {
        if (tmp._utern == i)
          continue;
        if (Graph[tmp._town][i] != NULL) {
          for (int j = -1; j <= 1; j++) {
            int tmp_speed = tmp._speed + j;
            if (Visited[i][tmp._town][tmp_speed] == true)
              continue;
            if (tmp_speed <= 0)
              continue;
            if (tmp_speed > Graph[tmp._town][i]->_c)
              continue;
            double tmp_time =
                Graph[tmp._town][i]->_d / static_cast<double>(tmp_speed);
            tmp_time += tmp._time;
            if (Cost[i][tmp._town][tmp_speed] < tmp_time)
              continue;
            Cost[i][tmp._town][tmp_speed] = tmp_time;
            PQ.push(State(tmp_time, tmp_speed, i, tmp._town));
          }
        }
      }
    }

    // Output
    if (min_time == -1) {
      cout << "unreachable" << endl;
    } else {
      cout << min_time << endl;
    }

    // Free
    for (int i = 0; i < 30; i++) {
      for (int j = 0; j < 30; j++) {
        if (Graph[i][j] != NULL)
          delete Graph[i][j];
      }
    }
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
const int INF = 1 << 29;

typedef double Weight;
struct Edge {
  int src, dst;
  Weight weight;
  int c; // c ÍOtÅÍ§À¬xAqueue ÅÍ¬x
  Edge(int src, int dst, Weight weight, int c)
      : src(src), dst(dst), weight(weight), c(c) {}
};

bool operator<(const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
             e.src != f.src ? e.src < f.src
         : e.dst != f.dst   ? e.dst < f.dst
                            : e.c < f.c;
}

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef pair<int, int> pii;

double dist[30][30][32]; // dist[i][j][k] = Xs[h k ÌóÔÅ j ©ç
                         // i ÉÂ­ÅZ£

double dijkstra(const Graph &g, int s, int t) {
  int n = g.size();
  REP(i, n) REP(j, n) REP(k, 32) dist[i][j][k] = INF;
  // pii prev[n][32];           // dist[i][j] = Xs[h j ÌóÔÅ i
  // ÉÂ­ÅZ£ prev[s][0] = pii(-1,0);
  priority_queue<Edge> Q;
  Q.push(Edge(s, s, 0, 0));
  while (!Q.empty()) {
    Edge e = Q.top();
    Q.pop();
    // printf("%d->%d %f %d\\n",e.src,e.dst,e.weight,e.c);
    if (e.dst == t && e.c == 1)
      break;
    REP(k, 3) {
      int v = e.c - 1 + k;
      if (v <= 0)
        continue;
      if (dist[e.dst][e.src][v] < e.weight)
        continue;
      FOR(f, g[e.dst]) {
        if (v > f->c)
          continue;
        if (f->dst == e.src)
          continue;
        double hoge = e.weight + f->weight / v;
        if (dist[f->dst][f->src][v] > hoge) {
          // prev[f->dst][f->src][v] = pii(f->src,e.c);
          dist[f->dst][f->src][v] = hoge;
          Q.push(Edge(f->src, f->dst, hoge, v));
        }
      }
    }
  }
  // pii hoge = pii(t,1);
  // while(hoge.first >= 0) {
  //   cout <<hoge.first<< " " << hoge.second << endl;
  //   hoge = prev[hoge.first][hoge.second];
  // }
  double res = INF;
  REP(i, n)
  res = min(res, dist[t][i][1]);
  return res;
}

int main() {
  int n, m;
  while (cin >> n >> m, n || m) {
    int s, t;
    cin >> s >> t;
    s--;
    t--;
    Graph g(n);
    REP(i, m) {
      int x, y, d, c;
      cin >> x >> y >> d >> c;
      x--;
      y--;
      g[x].push_back(Edge(x, y, d, c));
      g[y].push_back(Edge(y, x, d, c));
    }
    double res = dijkstra(g, s, t);
    if (res == INF)
      cout << "unreachable" << endl;
    else
      printf("%.5f\\n", res);
  }
}