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

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

#define rep(i, n) for (int i = 0; i < n; i++)
#define Rep(i, n) for (int i = 1; i <= n; i++)
#define sz(x) int(x.size())
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define YesorNo(a) printf(a ? "Yes\\n" : "No\\n")
#define endl '\\n'
#define fi first
#define se second
using ll = long long;
using P = pair<int, int>;
using Pl = pair<ll, ll>;
template <class T> using V = vector<T>;
const int dx[] = {0, 1, 0, -1, 1, 1, -1, -1};
const int dy[] = {1, 0, -1, 0, 1, -1, -1, 1};
const int inf = (1 << 30) - 1;
const ll infll = (1LL << 62) - 1;
ll ceil(const ll &a, const ll &b) { return ((a) + (b)-1) / b; }
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

void Dijkstra(int s, const vector<vector<P>> &g, vector<int> &dis) {
  priority_queue<P, vector<P>, greater<P>> que; // pair = (cost, v);
  dis[s] = 0;
  que.emplace(0, s);
  while (!que.empty()) {
    P p = que.top();
    que.pop();
    int now = p.second;
    if (dis[now] < p.first)
      continue;
    for (P np : g[now]) {
      int next = np.second;
      if (dis[next] > dis[now] + np.first) {
        dis[next] = dis[now] + np.first;
        que.emplace(dis[next], next);
      }
    }
  }
}

struct UnionFind { // UnionFindTree
  vector<int> d;
  UnionFind(int n) : d(n, -1) {}
  int find(int x) {
    if (d[x] < 0)
      return x;
    return d[x] = find(d[x]);
  }
  bool unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return false;
    if (-d[x] < -d[y])
      swap(x, y);
    d[x] += d[y];
    d[y] = x;
    return true;
  }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) { return -d[find(x)]; }
};

int main() {

  int h, w;
  cin >> h >> w;
  int sh, sw, gh, gw;
  cin >> sh >> sw >> gh >> gw;
  sh--;
  sw--;
  gh--;
  gw--;
  V<string> s(h);
  rep(i, h) cin >> s[i];

  auto makeId = [&](int y, int x) { return y * w + x; };

  UnionFind uf(h * w);
  rep(i, h) rep(j, w) {
    if (s[i][j] == '#')
      continue;
    rep(d, 4) {
      int ny = i + dy[d];
      int nx = j + dx[d];
      if (ny < 0 || ny >= h || nx < 0 || nx >= w)
        continue;
      if (s[ny][nx] == '#')
        continue;
      uf.unite(makeId(i, j), makeId(ny, nx));
    }
  }

  map<int, int> mp;
  int cnt = 0;
  rep(i, h) rep(j, w) {
    if (s[i][j] == '#')
      continue;
    int id = makeId(i, j);
    if (mp.find(uf.find(id)) == mp.end()) {
      mp[uf.find(id)] = cnt++;
    }
  }

  V<V<P>> g(cnt);
  V<set<int>> seen(cnt);
  rep(i, h) rep(j, w) {
    if (s[i][j] == '#')
      continue;
    for (int x = -2; x <= 2; ++x)
      for (int y = -2; y <= 2; ++y) {
        int nx = x + j;
        int ny = y + i;
        if (ny < 0 || ny >= h || nx < 0 || nx >= w)
          continue;
        if (s[ny][nx] == '#')
          continue;
        if (uf.find(makeId(i, j)) == uf.find(makeId(ny, nx)))
          continue;
        if (seen[mp[uf.find(makeId(i, j))]].find(mp[uf.find(makeId(ny, nx))]) !=
            seen[mp[uf.find(makeId(i, j))]].end())
          continue;
        seen[mp[uf.find(makeId(i, j))]].insert(mp[uf.find(makeId(ny, nx))]);
        g[mp[uf.find(makeId(i, j))]].emplace_back(1,
                                                  mp[uf.find(makeId(ny, nx))]);
      }
  }

  // rep(i,cnt) {
  //     rep(j,sz(g[i])) {
  //         printf(" [%d : %d] ", g[i][j].fi, g[i][j].se);
  //     }
  //     cout << endl;
  // }

  // rep(i,h)rep(j,w) {
  //     int ans = 0;
  //     if(s[i][j] == '#') ans = -1;
  //     else ans = mp[uf.find(makeId(i,j))];
  //     cout << ans << (j==w-1 ? '\\n' : ' ');
  // }

  V<int> dist(cnt, inf);
  int start = mp[uf.find(makeId(sh, sw))];
  Dijkstra(start, g, dist);
  int ans = dist[mp[uf.find(makeId(gh, gw))]];
  if (ans == inf)
    ans = -1;
  cout << ans << endl;
}

Error: TLE

Fixed submission:

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

#define rep(i, n) for (int i = 0; i < n; i++)
#define Rep(i, n) for (int i = 1; i <= n; i++)
#define sz(x) int(x.size())
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define YesorNo(a) printf(a ? "Yes\\n" : "No\\n")
#define endl '\\n'
#define fi first
#define se second
using ll = long long;
using P = pair<int, int>;
using Pl = pair<ll, ll>;
template <class T> using V = vector<T>;
const int dx[] = {0, 1, 0, -1, 1, 1, -1, -1};
const int dy[] = {1, 0, -1, 0, 1, -1, -1, 1};
const int inf = (1 << 30) - 1;
const ll infll = (1LL << 62) - 1;
ll ceil(const ll &a, const ll &b) { return ((a) + (b)-1) / b; }
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

void Dijkstra(int s, const vector<vector<P>> &g, vector<int> &dis) {
  priority_queue<P, vector<P>, greater<P>> que; // pair = (cost, v);
  dis[s] = 0;
  que.emplace(0, s);
  while (!que.empty()) {
    P p = que.top();
    que.pop();
    int now = p.second;
    if (dis[now] < p.first)
      continue;
    for (P np : g[now]) {
      int next = np.second;
      if (dis[next] > dis[now] + np.first) {
        dis[next] = dis[now] + np.first;
        que.emplace(dis[next], next);
      }
    }
  }
}

struct UnionFind { // UnionFindTree
  vector<int> d;
  UnionFind(int n) : d(n, -1) {}
  int find(int x) {
    if (d[x] < 0)
      return x;
    return d[x] = find(d[x]);
  }
  bool unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return false;
    if (-d[x] < -d[y])
      swap(x, y);
    d[x] += d[y];
    d[y] = x;
    return true;
  }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) { return -d[find(x)]; }
};

int main() {

  int h, w;
  cin >> h >> w;
  int sh, sw, gh, gw;
  cin >> sh >> sw >> gh >> gw;
  sh--;
  sw--;
  gh--;
  gw--;
  V<string> s(h);
  rep(i, h) cin >> s[i];

  auto makeId = [&](int y, int x) { return y * w + x; };

  UnionFind uf(h * w);
  rep(i, h) rep(j, w) {
    if (s[i][j] == '#')
      continue;
    rep(d, 4) {
      int ny = i + dy[d];
      int nx = j + dx[d];
      if (ny < 0 || ny >= h || nx < 0 || nx >= w)
        continue;
      if (s[ny][nx] == '#')
        continue;
      uf.unite(makeId(i, j), makeId(ny, nx));
    }
  }

  map<int, int> mp;
  int cnt = 0;
  rep(i, h) rep(j, w) {
    if (s[i][j] == '#')
      continue;
    int id = makeId(i, j);
    if (mp.find(uf.find(id)) == mp.end()) {
      mp[uf.find(id)] = cnt++;
    }
  }

  V<V<P>> g(cnt);
  V<V<bool>> seen(cnt, V<bool>(cnt));
  rep(i, h) rep(j, w) {
    if (s[i][j] == '#')
      continue;
    for (int x = -2; x <= 2; ++x)
      for (int y = -2; y <= 2; ++y) {
        int nx = x + j;
        int ny = y + i;
        if (ny < 0 || ny >= h || nx < 0 || nx >= w)
          continue;
        if (s[ny][nx] == '#')
          continue;
        if (uf.find(makeId(i, j)) == uf.find(makeId(ny, nx)))
          continue;
        if (seen[mp[uf.find(makeId(i, j))]][mp[uf.find(makeId(ny, nx))]])
          continue;
        seen[mp[uf.find(makeId(i, j))]][mp[uf.find(makeId(ny, nx))]] = true;
        g[mp[uf.find(makeId(i, j))]].emplace_back(1,
                                                  mp[uf.find(makeId(ny, nx))]);
      }
  }

  // rep(i,cnt) {
  //     rep(j,sz(g[i])) {
  //         printf(" [%d : %d] ", g[i][j].fi, g[i][j].se);
  //     }
  //     cout << endl;
  // }

  // rep(i,h)rep(j,w) {
  //     int ans = 0;
  //     if(s[i][j] == '#') ans = -1;
  //     else ans = mp[uf.find(makeId(i,j))];
  //     cout << ans << (j==w-1 ? '\\n' : ' ');
  // }

  V<int> dist(cnt, inf);
  int start = mp[uf.find(makeId(sh, sw))];
  Dijkstra(start, g, dist);
  int ans = dist[mp[uf.find(makeId(gh, gw))]];
  if (ans == inf)
    ans = -1;
  cout << ans << endl;
}