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

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>

using namespace std;

#define foreach(i, o)                                                          \\
  for (__typeof((o).begin()) i = (o).begin(); i != (o).end(); ++i)

const int max_place = 101;
const int max_time = 601;
const int MAX_V = 2010;
const int inf = 1 << 28;

struct edge {
  int src, dst;
  int cost;
  edge(int src, int dst, int cost) : src(src), dst(dst), cost(cost) {}
};

struct state {
  int pos;
  int prev;
  int cost;

  state(int pos, int prev, int cost) : pos(pos), prev(prev), cost(cost) {}

  bool operator>(const state &t) const {
    if (cost != t.cost)
      return cost > t.cost;
    if (prev != t.prev)
      return prev > t.prev;
    if (pos != t.pos)
      return pos > t.pos;
    return false;
  }

  /*
  bool operator<(const state &t)const{
    if(pos!=t.pos)return pos<t.pos;
    return false;
  }
  */
};

typedef vector<edge> edges;
typedef vector<edges> graph;

int convTime(const string &s) {
  int h = atoi(s.substr(0, 2).c_str());
  int m = atoi(s.substr(3, 2).c_str());
  return 60 * h + m;
}

string revTime(int t) {
  char buf[32];
  sprintf(buf, "%02d:%02d", t / 60, t % 60);
  return string(buf);
}

static int dist[MAX_V][MAX_V];
void johnson(const graph &tmp_g) {
  graph g = tmp_g;

  const int v = g.size();
  static int h[MAX_V];
  static int prev[MAX_V][MAX_V];

  for (int i = 0; i < v; ++i) {
    h[i] = 0;
  }

  for (int i = 0; i <= v; ++i) {
    bool end = true;
    for (int j = 0; j < v; ++j) {
      for (int k = 0; k < (int)g[j].size(); ++k) {
        edge e = g[j][k];
        int tmp = h[j] + e.cost;
        if (h[e.dst] > tmp) {
          h[e.dst] = tmp;
          end = false;
        }
      }
    }
    if (end)
      break;
    // do not detect an negative cycle.
  }

  for (int i = 0; i < v; ++i) {
    for (int j = 0; j < v; ++j) {
      dist[i][j] = inf;
      prev[i][j] = -1;
    }
    dist[i][i] = 0;
  }

  for (int i = 0; i < v; ++i) {
    for (int j = 0; j < (int)g[i].size(); ++j) {
      g[i][j].cost += h[i] - h[g[i][j].dst];
    }
  }

  for (int s = 0; s < v; ++s) {
    priority_queue<state, vector<state>, greater<state>> q;
    q.push(state(s, s, 0));
    while (!q.empty()) {
      state cur = q.top();
      q.pop();
      if (prev[s][cur.pos] != -1)
        continue;
      prev[s][cur.pos] = cur.prev;
      for (int i = 0; i < (int)g[cur.pos].size(); ++i) {
        edge e = g[cur.pos][i];
        int cost = cur.cost + e.cost;
        assert(cost >= 0);
        if (dist[s][e.dst] > cost) {
          dist[s][e.dst] = cost;
          q.push(state(e.dst, cur.pos, cost));
        }
      }
    }
    for (int i = 0; i < v; ++i) {
      dist[s][i] += h[i] - h[s];
    }
  }

  return;
}

int main() {
  int n;
  while (cin >> n && n) {
    int id = 1;
    int vid = 0;
    map<string, int> cityDict;
    map<int, string> revCityDict;
    set<int> cityEvTimes[max_place];
    graph g(MAX_V);

    map<pair<int, int>, int> vID;
    map<int, pair<int, int>> revID;

    for (int i = 0; i < n; ++i) {
      string from, ftime, to, ttime;
      int cost;

      cin >> from >> ftime >> to >> ttime >> cost;
      if (!cityDict.count(from)) {
        cityDict[from] = id;
        revCityDict[id] = from;
        ++id;
      }
      if (!cityDict.count(to)) {
        cityDict[to] = id;
        revCityDict[id] = to;
        ++id;
      }

      int src = cityDict[from];
      int dst = cityDict[to];
      int srcTime = convTime(ftime) - 480;
      int dstTime = convTime(ttime) - 480;

      if (dstTime >= 0 && dstTime < max_time && srcTime >= 0 &&
          srcTime < max_time) {
        if (!vID.count(make_pair(src, srcTime))) {
          vID[make_pair(src, srcTime)] = vid;
          revID[vid] = make_pair(src, srcTime);
          ++vid;
        }
        cityEvTimes[src].insert(srcTime);
        if (!vID.count(make_pair(dst, dstTime))) {
          vID[make_pair(dst, dstTime)] = vid;
          revID[vid] = make_pair(dst, dstTime);
          ++vid;
        }
        cityEvTimes[dst].insert(dstTime);

        g[vID[make_pair(src, srcTime)]].push_back(edge(
            vID[make_pair(src, srcTime)], vID[make_pair(dst, dstTime)], cost));
      }
    }
    g.resize(vID.size());

    for (int i = 1; i < id; ++i) {
      // sort( it->second.begin(), it->second.end() );
      foreach (it2, cityEvTimes[i]) {
        // g[it->first].push_back( edge(it->first, it->second[i], it->first,
        // it->second[i], 0) );
        set<int>::iterator it3 = it2;
        ++it3;
        if (it3 != cityEvTimes[i].end()) {
          g[vID[make_pair(i, *it2)]].push_back(
              edge(vID[make_pair(i, *it2)], vID[make_pair(i, *it3)], 0));
        }
      }
    }

    /*
    for(int i = 0; i < (int)g.size(); ++i){
      cout << i << ' ' << revCityDict[i] << ':' << endl;
      for(int j = 0; j < (int)g[i].size(); ++j){
        edge e = g[i][j];
        cout << revCityDict[e.src] << ' ' << revTime(e.srcTime) << ' ' <<
    revCityDict[e.dst] << ' ' << revTime(e.dstTime) << endl;
      }
    }
    cout << "---"<<endl;
    */

    /*
    foreach(i,revID){
      cout << revCityDict[i->second.first] << ' ' <<
    revTime(i->second.second+480) << endl;
    }
    */

    johnson(g);

    /*
    for(int i = 0; i < (int)g.size(); ++i){
      for(int j = 0; j < (int)g.size(); ++j){
        cout << i << ' ' << j << " : " << dist[i][j]  <<endl;
      }
    }
    */

    int res = inf;
    int kenInitial = cityDict["Tokyo"];
    int keikoInitial = cityDict["Hakodate"];

    // cout << kenInitial << ' ' << keikoInitial << endl;

    int ken_st, keiko_st;
    if (cityEvTimes[kenInitial].size() > 0 &&
        cityEvTimes[keikoInitial].size() > 0) {
      ken_st = vID[make_pair(kenInitial, *(cityEvTimes[kenInitial].begin()))];
      keiko_st =
          vID[make_pair(keikoInitial, *(cityEvTimes[keikoInitial].begin()))];

      // cout <<ken_st << ' ' <<keiko_st << endl;

      for (int i = 1; i < id; ++i) {
        foreach (ev1, cityEvTimes[i]) {
          int v1 = vID[make_pair(i, *ev1)];
          foreach (ev2, cityEvTimes[i]) {
            int v2 = vID[make_pair(i, *ev2)];
            int st = max(*ev1, *ev2) + 30;
            int from = -1;

            if (cityEvTimes[i].lower_bound(st) != cityEvTimes[i].end()) {
              from = vID[make_pair(i, *(cityEvTimes[i].lower_bound(st)))];
            }
            if (from < 0)
              continue;

            // cout << v1 << ' ' << v2 << ' ' << from << endl;

            foreach (ev3, cityEvTimes[kenInitial]) {
              if (*ev3 < st)
                continue;
              int v3 = vID[make_pair(kenInitial, *ev3)];
              foreach (ev4, cityEvTimes[keikoInitial]) {
                if (*ev4 < st)
                  continue;
                int v4 = vID[make_pair(keikoInitial, *ev4)];
                // cout << i << ' ' << revTime(*ev1+480) << ' ' <<
                // revTime(*ev2+480) << ' ' << revTime(*ev3+480) << ' ' <<
                // revTime(*ev4+480) << ' ' << revTime(st+480) << " : " <<
                // sssp[0][i][*ev1] << ' '<<sssp[1][i][*ev2]<<'
                // '<<sssp[2][kenInitial][*ev3]<< ' '
                // <<sssp[2][keikoInitial][*ev4] << endl;
                res = min(res, dist[ken_st][v1] + dist[keiko_st][v2] +
                                   dist[from][v3] + dist[from][v4]);
              }
            }
          }
        }
      }
    }

    if (res >= inf)
      res = 0;
    cout << res << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <string>

using namespace std;

#define foreach(i, o)                                                          \\
  for (__typeof((o).begin()) i = (o).begin(); i != (o).end(); ++i)
const int max_place = 101;
const int max_time = 601;
const int inf = 1 << 28;

struct edge {
  int src, srcTime, dst, dstTime;
  int cost;
  edge(int src, int srcTime, int dst, int dstTime, int cost)
      : src(src), srcTime(srcTime), dst(dst), dstTime(dstTime), cost(cost) {}
};

struct state {
  int place, time;
  int cost;

  state(int place, int time, int cost) : place(place), time(time), cost(cost) {}

  bool operator>(const state &t) const {
    if (cost != t.cost)
      return cost > t.cost;
    if (place != t.place)
      return place > t.place;
    if (time != t.time)
      return time > t.time;
    return false;
  }

  bool operator<(const state &t) const {
    if (place != t.place)
      return place < t.place;
    if (time != t.time)
      return time < t.time;
    return false;
  }
};

typedef vector<edge> edges;
typedef vector<edges> graph;

int convTime(const string &s) {
  int h = atoi(s.substr(0, 2).c_str());
  int m = atoi(s.substr(3, 2).c_str());
  return 60 * h + m;
}

string revTime(int t) {
  char buf[32];
  sprintf(buf, "%02d:%02d", t / 60, t % 60);
  return string(buf);
}

int sssp[3][max_place][max_time];

int fsssp(const graph &g, int who, int iniPlace, int iniTime) {
  priority_queue<state, vector<state>, greater<state>> q;

  q.push(state(iniPlace, iniTime, 0));
  sssp[who][iniPlace][iniTime] = 0;
  while (!q.empty()) {
    state cur = q.top();
    q.pop();
    for (int i = 0; i < (int)g[cur.place].size(); ++i) {
      edge e = g[cur.place][i];
      state next(e.dst, e.dstTime, cur.cost + e.cost);
      if (cur.time <= e.srcTime &&
          sssp[who][next.place][next.time] > next.cost) {
        sssp[who][next.place][next.time] = next.cost;
        q.push(next);
      }
    }
  }

  return 0;
}

int main() {
  int n;
  while (cin >> n && n) {
    int id = 1;
    map<string, int> cityDict;
    map<int, string> revCityDict;
    map<int, vector<int>> cityEvTimes;
    graph g(max_place);

    for (int i = 0; i < n; ++i) {
      string from, ftime, to, ttime;
      int cost;

      cin >> from >> ftime >> to >> ttime >> cost;
      if (!cityDict.count(from)) {
        cityDict[from] = id;
        revCityDict[id] = from;
        ++id;
      }
      if (!cityDict.count(to)) {
        cityDict[to] = id;
        revCityDict[id] = to;
        ++id;
      }

      int src = cityDict[from];
      int dst = cityDict[to];
      int srcTime = convTime(ftime) - 480;
      int dstTime = convTime(ttime) - 480;

      if (dstTime >= 0 && dstTime < max_time && srcTime >= 0 &&
          srcTime < max_time) {
        cityEvTimes[src].push_back(srcTime);
        cityEvTimes[dst].push_back(dstTime);
        g[src].push_back(edge(src, srcTime, dst, dstTime, cost));
      }
    }
    g.resize(id);

    /*
    foreach(it, cityEvTimes){
      sort( it->second.begin(), it->second.end() );
      for(int i = 0; i < (int)it->second.size(); ++i){
        g[it->first].push_back( edge(it->first, it->second[i], it->first,
    it->second[i], 0) ); if( 1+i < (int)it->second.size() ){
          g[it->first].push_back( edge(it->first, it->second[i], it->first,
    it->second[i+1], 0) );
        }
      }
    }
    */

    /*
    for(int i = 0; i < (int)g.size(); ++i){
      cout << i << ' ' << revCityDict[i] << ':' << endl;
      for(int j = 0; j < (int)g[i].size(); ++j){
        edge e = g[i][j];
        cout << revCityDict[e.src] << ' ' << revTime(e.srcTime) << ' ' <<
    revCityDict[e.dst] << ' ' << revTime(e.dstTime) << endl;
      }
    }
    cout << "---"<<endl;
    */

    int res = inf;

    for (int i = 0; i < 3; ++i) {
      for (int j = 0; j < max_place; ++j) {
        for (int k = 0; k < max_time; ++k) {
          sssp[i][j][k] = inf;
        }
      }
    }

    int kenInitial = cityDict["Tokyo"];
    int keikoInitial = cityDict["Hakodate"];

    // cout << kenInitial << ' ' << keikoInitial << endl;

    fsssp(g, 0, kenInitial, 0);
    fsssp(g, 1, keikoInitial, 0);

    for (int i = 1; i < id; ++i) {
      foreach (ev1, cityEvTimes[i]) {
        foreach (ev2, cityEvTimes[i]) {
          int st = max(*ev1, *ev2) + 30;

          for (int j = 0; j < max_place; ++j) {
            for (int k = 0; k < max_time; ++k) {
              sssp[2][j][k] = inf;
            }
          }
          fsssp(g, 2, i, st);

          /*
          for(int k = 1; k < id; ++k){
            foreach(ev, cityEvTimes[k]){
              cout << i << ' ' << k << ' ' << revTime(*ev+480) << " : " <<
          sssp[2][i][*ev] << endl;
            }
          }
          */

          foreach (ev3, cityEvTimes[kenInitial]) {
            if (*ev3 < st)
              continue;
            foreach (ev4, cityEvTimes[keikoInitial]) {
              if (*ev4 < st)
                continue;
              // cout << i << ' ' << revTime(*ev1+480) << ' ' <<
              // revTime(*ev2+480) << ' ' << revTime(*ev3+480) << ' ' <<
              // revTime(*ev4+480) << ' ' << revTime(st+480) << " : " <<
              // sssp[0][i][*ev1] << ' '<<sssp[1][i][*ev2]<<'
              // '<<sssp[2][kenInitial][*ev3]<< ' '
              // <<sssp[2][keikoInitial][*ev4] << endl;
              res = min(res, sssp[0][i][*ev1] + sssp[1][i][*ev2] +
                                 sssp[2][kenInitial][*ev3] +
                                 sssp[2][keikoInitial][*ev4]);
            }
          }
        }
      }
    }

    if (res >= inf)
      res = 0;
    cout << res << endl;
  }
  return 0;
}