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

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <sstream>
#include <string>
#include <tuple>
#include <unordered_set>
#include <vector>

using namespace std;
using ll = long long;

#define all(c) (c).begin(), (c).end()
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define pb(e) push_back(e)
#define mp(a, b) make_pair(a, b)
#define fr first
#define sc second

const ll INF = 1e9;
const ll MOD = 1e9 + 7;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
using P = pair<int, int>;
int n, m, k;

namespace std {
template <> class hash<P> {
public:
  size_t operator()(const P &p) const {
    size_t seed = 0;

    seed ^= p.first + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    seed ^= p.second + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    return seed;
  }
};
template <> class hash<tuple<P, int>> {
public:
  size_t operator()(const tuple<P, int> &t) const {
    size_t seed = 0;

    P p = get<0>(t);
    int a = get<1>(t);
    seed ^= p.first + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    seed ^= p.second + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    seed ^= a + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    return seed;
  }
};
} // namespace std
unordered_set<P> s, t, all;
unordered_set<tuple<P, int>> visited;

template <typename F>
int dfs(int y, int x, int count, const unordered_set<P> &s, F func,
        const unordered_set<P> &all) {
  // printf("%d: %d %d %d %lu\\n", __LINE__, y, x, count, visited.size());
  int ret = 2;
  if (func(P(y, x))) {
    return count;
  }
  for (int dy = -1; dy <= 1; dy++) {
    for (int dx = -1; dx <= 1; dx++) {
      if (dy == 0 && dx == 0)
        continue;
      int ny = y + dy;
      int nx = x + dx;
      if (visited.count(make_tuple(P(ny, nx), count))) {
        continue;
      }
      if (ny < 0 || n <= ny)
        continue;
      if (nx < 0 || m <= nx)
        continue;
      if (all.count(P(ny, nx))) {
        visited.insert(make_tuple(P(ny, nx), count));
        // printf("\\t%d: %d %d %d %d\\n", __LINE__, ny, nx, count,
        //        visited.size());
        ret = min(ret, dfs(ny, nx, count, s, func, all));
      }
      if (count == 0) {
        // printf("\\t%d: %d %d %d %d\\n", __LINE__, ny, nx, count,
        // visited.size());
        ret = min(ret, dfs(ny, nx, count + 1, s, func, all));
      }
    }
  }

  return ret;
}

template <typename F> int f(const unordered_set<P> &s, F func) {
  int ret = 2;
  visited.clear();
  for (auto &&e : s) {
    int a = dfs(e.first, e.second, 0, s, func, all);
    // printf("%d %d %d\\n", e.first, e.second, a);
    ret = min(ret, a);
  }

  return ret;
}

int main() {
  cin >> n >> m >> k;
  rep(i, k) {
    int x, y;
    cin >> y >> x;
    all.insert(P(y, x));
    if (y == 0 || x == m - 1)
      s.insert(P(y, x));
    if (x == 0 || y == n - 1)
      t.insert(P(y, x));
  }
  int a = f(s, [](P p) { return p.second == 0 || p.first == n - 1; });
  a = min(a, f(t, [](P p) { return p.first == 0 || p.second == m - 1; }));
  cout << a << endl;
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <tuple>
#include <vector>

using namespace std;
using ll = long long;

#define all(c) (c).begin(), (c).end()
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define pb(e) push_back(e)
#define mp(a, b) make_pair(a, b)
#define fr first
#define sc second

const ll INF = 1e9;
const ll MOD = 1e9 + 7;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
using P = pair<int, int>;
int n, m, k;
set<P> s, t, all;
set<tuple<P, int>> visited;

template <typename F>
int dfs(int y, int x, int count, const set<P> &s, F func, const set<P> &all) {
  // printf("%d: %d %d %d %lu\\n", __LINE__, y, x, count, visited.size());
  int ret = 2;
  if (func(P(y, x))) {
    return count;
  }
  for (int dy = -1; dy <= 1; dy++) {
    for (int dx = -1; dx <= 1; dx++) {
      if (dy == 0 && dx == 0)
        continue;
      int ny = y + dy;
      int nx = x + dx;
      if (visited.count(make_tuple(P(ny, nx), count))) {
        continue;
      }
      if (ny < 0 || n <= ny)
        continue;
      if (nx < 0 || m <= nx)
        continue;
      if (all.count(P(ny, nx))) {
        visited.insert(make_tuple(P(ny, nx), count));
        // printf("\\t%d: %d %d %d %d\\n", __LINE__, ny, nx, count,
        //        visited.size());
        ret = min(ret, dfs(ny, nx, count, s, func, all));
      }
      if (count == 0) {
        // printf("\\t%d: %d %d %d %d\\n", __LINE__, ny, nx, count,
        // visited.size());
        ret = min(ret, dfs(ny, nx, count + 1, s, func, all));
      }
    }
  }

  return ret;
}

template <typename F> int f(const set<P> &s, F func) {
  int ret = 2;
  visited.clear();
  for (auto &&e : s) {
    int a = dfs(e.first, e.second, 0, s, func, all);
    // printf("%d %d %d\\n", e.first, e.second, a);
    ret = min(ret, a);
  }

  return ret;
}

int main() {
  cin >> n >> m >> k;
  rep(i, k) {
    int x, y;
    cin >> y >> x;
    all.insert(P(y, x));
    if (y == 0 || x == m - 1)
      s.insert(P(y, x));
    if (x == 0 || y == n - 1)
      t.insert(P(y, x));
  }
  int a = f(s, [](P p) { return p.second == 0 || p.first == n - 1; });
  a = min(a, f(t, [](P p) { return p.first == 0 || p.second == m - 1; }));
  cout << a << endl;
  return 0;
}