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

#include <algorithm>
#include <unordered_map>
#include <vector>
class Compression {
public:
  Compression(const std::vector<int> &list) : value_(list) {
    std::sort(begin(value_), end(value_));
    value_.erase(std::unique(begin(value_), end(value_)), end(value_));
    for (int i = 0; i < value_.size(); ++i)
      index_[value_[i]] = i;
  }
  int size() const { return value_.size(); }
  int index(const int v) const { return index_.at(v); }
  int operator[](const int i) const { return value_.at(i); }

private:
  std::unordered_map<int, int> index_;
  std::vector<int> value_;
};

#include <bits/stdc++.h>
using namespace std;

enum { BLANK = -2, WALL };
enum { Y, X };
const int NEXT[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

struct Wall {
  int px, py, qx, qy;
};
struct Query {
  int sx, sy, gx, gy;
};

int range(int x, int lower, int upper) { return max(lower, min(upper, x)); }

void flood_fill(vector<vector<int>> &field, int y, int x, int color) {
  const int h = field.size();
  const int w = field.front().size();
  field[y][x] = color;
  for (const auto &d : NEXT) {
    int ny = y + d[Y];
    int nx = x + d[X];
    if (ny < 0 || h <= ny || nx < 0 || w <= nx)
      continue;
    if (field[ny][nx] == BLANK)
      flood_fill(field, ny, nx, color);
  }
}

int main() {
  int W, H, M;
  cin >> W >> H >> M;
  W *= 2;
  H *= 2;

  vector<int> raw_x({0, W}), raw_y({0, H});

  vector<Wall> wall(M);
  for (auto &w : wall) {
    cin >> w.px >> w.py >> w.qx >> w.qy;
    w.px *= 2;
    w.py *= 2;
    w.qx *= 2;
    w.qy *= 2;
    for (int d : {-1, 0, 1}) {
      raw_x.insert(begin(raw_x),
                   {range(w.px + d, 0, W), range(w.qx + d, 0, W)});
      raw_y.insert(begin(raw_y),
                   {range(w.py + d, 0, H), range(w.qy + d, 0, H)});
    }
  }

  int Q;
  cin >> Q;
  vector<Query> query(Q);
  for (auto &q : query) {
    cin >> q.sx >> q.sy >> q.gx >> q.gy;
    q.sx *= 2;
    q.sy *= 2;
    q.gx *= 2;
    q.gy *= 2;
    raw_x.insert(begin(raw_x), {q.sx, q.gx});
    raw_y.insert(begin(raw_y), {q.sy, q.gy});
  }

  Compression x(raw_x), y(raw_y);

  vector<vector<int>> field(y.size(), vector<int>(x.size(), BLANK));
  for (int i = 0; i < y.size(); ++i)
    field[i][0] = field[i][x.size() - 1] = WALL;
  for (int j = 0; j < x.size(); ++j)
    field[0][j] = field[y.size() - 1][j] = WALL;
  for (const auto &w : wall) {
    if (w.px != w.qx)
      for (int j = x.index(min(w.px, w.qx)); j <= x.index(max(w.px, w.qx)); ++j)
        field[y.index(w.py)][j] = WALL;
    if (w.py != w.qy)
      for (int i = y.index(min(w.py, w.qy)); i <= y.index(max(w.py, w.qy)); ++i)
        field[i][x.index(w.px)] = WALL;
  }

  // 塗りつぶし
  int color = 0;
  for (int i = 0; i < y.size(); ++i)
    for (int j = 0; j < x.size(); ++j) {
      if (field[i][j] == BLANK)
        flood_fill(field, i, j, color++);
    }

  // ワーシャルフロイド
  const int INF = 1000000000;
  const int NEXTNEXT[4][2] = {{-2, 0}, {2, 0}, {0, -2}, {0, 2}};
  vector<vector<int>> cost(color, vector<int>(color, INF));
  for (int v = 0; v < color; ++v)
    cost[v][v] = 0;
  for (int i = 0; i < y.size(); ++i)
    for (int j = 0; j < x.size(); ++j) {
      if (field[i][j] == WALL)
        continue;
      for (const auto &d : NEXTNEXT) {
        int ny = i + d[Y];
        int nx = j + d[X];
        if (ny < 0 || y.size() <= ny || nx < 0 || x.size() <= nx)
          continue;
        int u = field[i][j];
        int v = field[ny][nx];
        if (v == WALL)
          continue;
        if (u == v)
          continue;
        cost[u][v] = cost[v][u] = 1;
      }
    }
  for (int k = 0; k < color; ++k)
    for (int u = 0; u < color; ++u)
      for (int v = 0; v < color; ++v)
        cost[u][v] = min(cost[u][v], cost[u][k] + cost[k][v]);

  for (const auto &q : query) {
    cout << cost[field[y.index(q.sy)][x.index(q.sx)]]
                [field[y.index(q.gy)][x.index(q.gx)]]
         << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <map>
#include <vector>

class Compression {
public:
  Compression(const std::vector<int> &list) : value_(list) {
    std::sort(begin(value_), end(value_));
    value_.erase(std::unique(begin(value_), end(value_)), end(value_));
    for (int i = 0; i < value_.size(); ++i)
      index_[value_[i]] = i;
  }
  int size() const { return value_.size(); }
  int index(const int v) const { return index_.at(v); }
  int operator[](const int i) const { return value_.at(i); }

private:
  std::map<int, int> index_;
  std::vector<int> value_;
};

#include <bits/stdc++.h>
using namespace std;

enum { BLANK = false, WALL = true };
enum { Y, X };
const int NEXT[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

struct Wall {
  int px, py, qx, qy;
};
struct Query {
  int sx, sy, gx, gy;
};

int range(int x, int lower, int upper) { return max(lower, min(upper, x)); }

int Dijkstra(const vector<vector<bool>> &field, int sx, int sy, int gx,
             int gy) {
  const int h = field.size();
  const int w = field.front().size();

  typedef tuple<int, int, int> Node;

  vector<vector<bool>> visited(h, vector<bool>(w, false));
  priority_queue<Node, vector<Node>, greater<Node>> q;
  q.emplace(0, sy, sx);
  while (!q.empty()) {
    int cost, y, x;
    tie(cost, y, x) = q.top();
    q.pop();
    if (y == gy && x == gx)
      return cost;
    if (visited[y][x])
      continue;
    visited[y][x] = true;
    //     cout << cost << ", " << y << ", " << x << endl;
    for (const auto &d : NEXT) {
      int ncost = cost;
      int ny = y + d[Y];
      int nx = x + d[X];
      if (ny < 0 || h <= ny || nx < 0 || w <= nx)
        continue;
      if (field[ny][nx] == WALL) {
        ny += d[Y];
        nx += d[X];
        ++ncost;
      }
      if (ny < 0 || h <= ny || nx < 0 || w <= nx)
        continue;
      if (!visited[ny][nx])
        q.emplace(ncost, ny, nx);
    }
  }

  return -1;
}

int main() {
  int W, H, M;
  cin >> W >> H >> M;
  W *= 2;
  H *= 2;

  vector<int> raw_x({0, W}), raw_y({0, H});

  vector<Wall> wall(M);
  for (auto &w : wall) {
    cin >> w.px >> w.py >> w.qx >> w.qy;
    w.px *= 2;
    w.py *= 2;
    w.qx *= 2;
    w.qy *= 2;
    for (int d : {-1, 0, 1}) {
      raw_x.insert(begin(raw_x),
                   {range(w.px + d, 0, W), range(w.qx + d, 0, W)});
      raw_y.insert(begin(raw_y),
                   {range(w.py + d, 0, H), range(w.qy + d, 0, H)});
    }
  }

  int Q;
  cin >> Q;
  vector<Query> query(Q);
  for (auto &q : query) {
    cin >> q.sx >> q.sy >> q.gx >> q.gy;
    q.sx *= 2;
    q.sy *= 2;
    q.gx *= 2;
    q.gy *= 2;
    raw_x.insert(begin(raw_x), {q.sx, q.gx});
    raw_y.insert(begin(raw_y), {q.sy, q.gy});
  }

  Compression x(raw_x), y(raw_y);
  vector<vector<bool>> field(y.size(), vector<bool>(x.size(), BLANK));
  for (int i = 0; i < y.size(); ++i)
    field[i][0] = field[i][x.size() - 1] = WALL;
  for (int j = 0; j < x.size(); ++j)
    field[0][j] = field[y.size() - 1][j] = WALL;
  for (const auto &w : wall) {
    if (w.px != w.qx)
      for (int j = x.index(min(w.px, w.qx)); j <= x.index(max(w.px, w.qx)); ++j)
        field[y.index(w.py)][j] = WALL;
    if (w.py != w.qy)
      for (int i = y.index(min(w.py, w.qy)); i <= y.index(max(w.py, w.qy)); ++i)
        field[i][x.index(w.px)] = WALL;
  }

  //   for(auto i: field) {
  //     for(auto j: i)cout<<" "<<j;
  //     cout<<endl;
  //   }

  for (const auto &q : query) {
    cout << Dijkstra(field, x.index(q.sx), y.index(q.sy), x.index(q.gx),
                     y.index(q.gy))
         << endl;
  }
}