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

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
using namespace std;

// (x,y)
typedef pair<int, int> P;
// ( 速度 , (前の町,今の町) )
typedef pair<int, P> Node;
// (cost,Node)
typedef pair<double, Node> State;

const int MAX_V = 31;
const double INF = 1e200;

struct edge {
  int to, d, c;
  edge(int to_, int d_, int c_) {
    to = to_;
    d = d_;
    c = c_;
  }
};

// グラフ
vector<edge> G[MAX_V];
// スタートからゴールに辿りつけるかどうか
bool memo[MAX_V];
bool is_connect;

// 入力
int n, m;

// 初期化
void init() {
  is_connect = false;
  for (int i = 0; i < MAX_V; i++) {
    G[i].clear();
  }
}

// 辺の追加
void add_edge(int x, int y, int d, int c) {
  edge e(y, d, c);
  G[x].push_back(e);
  e.to = x;
  G[y].push_back(e);
}

// スタートからゴールに辿りつけるかどうかチェック
void check(int v, int g) {
  if (v == g) {
    is_connect = true;
  }
  if (memo[v])
    return;
  memo[v] = true;

  for (int i = 0; i < G[v].size(); i++) {
    int to = G[v][i].to;
    if (memo[to])
      continue;
    check(to, g);
  }
}

// ダイクストラ法
double solve(int s, int g) {
  // d[v][x][y] := 速度v, 前の町x, 今の町yまでの最小コスト
  double d[31][31][31];
  // 訪れたかどうか
  bool visited[31][31][31];
  // 初期化
  for (int y = 0; y < MAX_V; y++) {
    for (int x = 0; x < MAX_V; x++) {
      for (int v = 0; v < 31; v++) {
        d[v][y][x] = INF;
        visited[v][y][x] = false;
      }
    }
  }

  // State := (cost,Node), Node := ( 速度 , (前の町,今の町) )
  priority_queue<State, vector<State>, greater<State>> q;
  for (int i = 0; i < G[s].size(); i++) {
    int to = G[s][i].to;
    double dis = G[s][i].d;

    Node start(1, P(s, to));
    q.push(State(dis, start));
    d[1][s][to] = dis;
  }

  double ans = INF;
  int cnt = 0;
  while (!q.empty()) {
    // cnt++;
    // if( cnt >= 2000000 ) break;

    // 値を取り出す
    double now_cost = q.top().first;
    int v = q.top().second.first;
    int x = q.top().second.second.first;
    int y = q.top().second.second.second;
    q.pop();

    if (now_cost >= ans || visited[v][x][y])
      continue;
    visited[v][x][y] = true;

    // 目的地のとき
    if (y == g && v == 1) {
      ans = min(ans, now_cost);
      break;
    }

    for (int i = 0; i < G[y].size(); i++) {
      int to = G[y][i].to;
      int dis = G[y][i].d;
      int c = G[y][i].c;
      if (to == x)
        continue;

      for (int dv = -1; dv <= 1; dv++) {
        int next_v = v + dv;
        if (next_v > c || next_v <= 0)
          continue;

        double cost = (double)dis / next_v;
        if (now_cost + cost < d[next_v][y][to]) {
          d[next_v][y][to] = now_cost + cost;

          Node next(next_v, P(y, to));
          State p(now_cost + cost, next);
          q.push(p);
        }
      }
    }
  }
  return ans;
}

int main() {
  while (scanf("%d %d", &n, &m), n || m) {
    // 初期化
    init();

    int s, g;
    cin >> s >> g;

    for (int i = 0; i < m; i++) {
      int x, y, d, c;
      scanf("%d %d %d %d", &x, &y, &d, &c);
      add_edge(x, y, d, c);
    }

    {
      // スタートからゴールに辿りつけるかどうか
      for (int i = 0; i < MAX_V; i++) {
        memo[i] = false;
      }
      check(s, g);
    }

    // ゴールに辿りつけないとき
    if (is_connect == false) {
      puts("unreachable");
    } else {
      double ans = solve(s, g);
      printf("%.4f\\n", ans);
    }
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
using namespace std;

// (x,y)
typedef pair<int, int> P;
// ( 速度 , (前の町,今の町) )
typedef pair<int, P> Node;
// (cost,Node)
typedef pair<double, Node> State;

const int MAX_V = 31;
const double INF = 100000;

struct edge {
  int to, d, c;
  edge(int to_, int d_, int c_) {
    to = to_;
    d = d_;
    c = c_;
  }
};

// グラフ
vector<edge> G[MAX_V];
// スタートからゴールに辿りつけるかどうか
bool is_connect;

// 入力
int n, m;

// 初期化
void init() {
  is_connect = false;
  for (int i = 0; i < MAX_V; i++) {
    G[i].clear();
  }
}

// 辺の追加
void add_edge(int x, int y, int d, int c) {
  edge e(y, d, c);
  G[x].push_back(e);
  e.to = x;
  G[y].push_back(e);
}

// スタートからゴールに辿りつけるかどうかチェック
void check(int v, int g, map<int, bool> memo) {
  if (v == g) {
    is_connect = true;
  }
  if (memo[v])
    return;
  memo[v] = true;

  for (int i = 0; i < G[v].size(); i++) {
    int to = G[v][i].to;
    if (memo[to])
      continue;
    check(to, g, memo);
  }
}

// ダイクストラ法
double solve(int s, int g) {
  // d[v][x][y] := 速度v, 前の町x, 今の町yまでの最小コスト
  double d[31][31][31];
  // 訪れたかどうか
  bool visited[31][31][31];
  // 初期化
  for (int y = 0; y < MAX_V; y++) {
    for (int x = 0; x < MAX_V; x++) {
      for (int v = 0; v < 31; v++) {
        d[v][y][x] = INF;
        visited[v][y][x] = false;
      }
    }
  }

  // State := (cost,Node), Node := ( 速度 , (前の町,今の町) )
  priority_queue<State, vector<State>, greater<State>> q;
  for (int i = 0; i < G[s].size(); i++) {
    int to = G[s][i].to;
    double dis = G[s][i].d;

    Node start(1, P(s, to));
    q.push(State(dis, start));
    d[1][s][to] = dis;
  }

  double ans = INF;
  while (!q.empty()) {
    // 値を取り出す
    double now_cost = q.top().first;
    int v = q.top().second.first;
    int x = q.top().second.second.first;
    int y = q.top().second.second.second;
    q.pop();

    if (now_cost >= ans || visited[v][x][y])
      continue;
    visited[v][x][y] = true;

    // 目的地のとき
    if (y == g && v == 1) {
      ans = min(ans, now_cost);
      continue;
    }

    for (int i = 0; i < G[y].size(); i++) {
      int to = G[y][i].to;
      int dis = G[y][i].d;
      int c = G[y][i].c;
      if (to == x)
        continue;

      for (int dv = -1; dv <= 1; dv++) {
        int next_v = v + dv;
        if (next_v > c || next_v <= 0)
          continue;

        double cost = (double)dis / next_v;
        if (now_cost + cost < d[next_v][y][to]) {
          d[next_v][y][to] = now_cost + cost;

          Node next(next_v, P(y, to));
          State p(now_cost + cost, next);
          q.push(p);
        }
      }
    }
  }
  return ans;
}

int main() {
  while (cin >> n >> m, n || m) {
    // 初期化
    init();

    int s, g;
    cin >> s >> g;

    for (int i = 0; i < m; i++) {
      int x, y, d, c;
      cin >> x >> y >> d >> c;
      add_edge(x, y, d, c);
    }

    {
      // スタートからゴールに辿りつけるかどうか
      map<int, bool> memo;
      for (int i = 0; i < MAX_V; i++) {
        memo[i] = false;
      }
      check(s, g, memo);
    }

    // ゴールに辿りつけないとき
    if (is_connect == false) {
      cout << "unreachable" << endl;
    } else {
      double ans = solve(s, g);
      cout << ans << endl;
    }
  }
}