Problem:
Problem F: Great Devil Sakanikia
Problem
大悪魔サカーニャは今日も天敵の猫に襲われていた。
いつもやられている訳にはいかないので、秘密兵器を購入した。
この秘密兵器は、巨大な岩を生成することで猫の移動経路を塞ぎ、猫がこちらに近づけないようにすることができる。
今、サカーニャと一匹の猫がマス(0,0),(
n
−1,0),(
n
−1,
m
−1),(0,
m
−1)で囲まれた長方形の閉区間内にいる。
マス(0,0)に猫、マス(
n
−1,
m
−1)にサカーニャがいる。
猫は上下左右の隣接したマスに移動することができるが、区間外に出ることはできない。
いくつかのマスは、穴や障害物の影響で侵入することができない。
サカーニャは、あるマスに1つ岩を生成することでそのマスに猫が侵入できなくすることができる。
ただし、マス(0,0)とマス(
n
−1,
m
−1)に岩を生成することはできない。
マス(0,0)からマス(
n
−1,
m
−1)までの移動経路を塞ぐために必要な、生成する岩の数の最小値を求めよ。
Input
n
m
k
x
1
y
1
...
x
k
y
k
入力はすべて整数で与えられる。
1行目にマスの大きさを表す２つの整数
n
と
m
、侵入できないマスの数
k
が空白区切りで与えられる。
2行目から
k
行に侵入できないマスの座標が与えられる。
Constraints
入力は以下の条件を満たす。
2 ≤
n
,
m
≤ 10
5
0 ≤
k
≤ min(
n
×
m
−2,10
5
)
0 ≤
x
i
≤
n
− 1
0 ≤
y
i
≤
m
− 1
(
x
i
,
y
i
) ≠ (
x
j
,
y
j
) (
i
≠
j
)
(
x
i
,
y
i
) ≠ (0,0) ≠ (
n
−1,
m
−1)
Output
マス(0,0)からマス(
n
−1,
m
−1)までの移動経路を塞ぐために必要な、生成する岩の数の最小値を1行に出力せよ。
Sample Input 1
3 5 2
0 2
2 2
Sample Output 1
1
Sample Input 2
5 5 3
0 2
2 2
4 1
Sample Output 2
2

Submitted solutions:

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

using VS = vector<string>;    using LL = long long;
using VI = vector<int>;       using VVI = vector<VI>;
using PII = pair<int, int>;   using PLL = pair<LL, LL>;
using VL = vector<LL>;        using VVL = vector<VL>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))
#define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++)
#define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--)
#define debug(x) cerr << #x << ": " << x << endl
const int INF = 1e9;                          const LL LINF = 1e16;
const LL MOD = 1000000007;                    const double PI = acos(-1.0);
int DX[8] = { 0, 0, 1, -1, 1, 1, -1, -1 };    int DY[8] = { 1, -1, 0, 0, 1, -1, 1, -1 };

/* -----  2018/07/05  Problem: AOJ 3005 / Link: https://onlinejudge.u-aizu.ac.jp/challenges/search/volumes/3005  ----- */
/* ------問題------



-----問題ここまで----- */
/* -----解説等-----



----解説ここまで---- */


struct UnionFind {
	vector<int> data;
	UnionFind(int n) { data.assign(n, -1); }
	bool unionSet(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	bool same(int x, int y) { return root(x) == root(y); }
	int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
	int size(int x) { return -data[root(x)]; }
};
// UnionFind uf(n); uf.unionSet(i,j); if(uf.same(x,y))
#define IN(a, x, b) (a<=x && x<b)


int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);

	int H, W, K;
	cin >> W >> H >> K;
	map<PII, int>Point;
	VI x(K), y(K);
	int pc =1;
	FOR(i, 0, K) {
		cin >> x[i] >> y[i];
		Point[PII(y[i], x[i])] = pc++;
	}

	// uf
	UnionFind uf(K + 2 * (H + W));
	int A = pc++;
	int B = pc++;

	FOR(i, 0, K) {
		FOR(d, 0, 8) {
			int ny = y[i] + DY[d];
			int nx = x[i] + DX[d];
			if (!IN(0, nx, W) || !IN(0, ny, H)) {
				if (ny < 0) uf.unionSet(Point[PII(y[i], x[i])], A);
				if (nx < 0) uf.unionSet(Point[PII(y[i], x[i])], B);
				if (ny > H - 1) uf.unionSet(Point[PII(y[i], x[i])], B);
				if (nx > W - 1) uf.unionSet(Point[PII(y[i], x[i])], A);
			}
			else {
				if (Point.find(PII(ny, nx)) == Point.end()) continue;
				uf.unionSet(Point[PII(y[i],x[i])], Point[PII(ny, nx)]);
			}
		}
	}
	if (uf.same(A, B)) {
		cout << "0" << endl;
	}
	else {
		int f = 0;
		int dy[] = { -2,-2,-2,-2,-2,-1,0,1,2,2,2,2,2,1,0,-1 };
		int dx[] = { -2,-1,0,1,2,2,2,2,2,1,0,-1,-2,-2,-2,-2 };
		FOR(i, 0, K) {
			if (!uf.same(Point[PII(y[i], x[i])], A) && !uf.same(Point[PII(y[i], x[i])], B)) continue;
			int join = uf.same(Point[PII(y[i], x[i])], B);
			FOR(d, 0, 16) {
				int ny = y[i] + dy[d];
				int nx = x[i] + dx[d];
				if (!IN(0, nx, W) || !IN(0, ny, H)) {
					if ((ny < 0 && join == 1) ||
						(nx < 0 && join == 0) ||
						(ny > H - 1 && join == 0) ||
						(nx > W - 1 && join == 1)){
						f = 1;
					}
				}
				else {
					if (Point.find(PII(ny, nx)) == Point.end()) continue;
					if (uf.same(Point[PII(ny, nx)], A + !join)) {
						f = 1;
					}
				}
			}
		}
		cout << (f ? 1 : 2) << endl;
	}
	//debug(A);
	//debug(B);
	//int yy, xx;
	//while (cin >> yy >> xx) {
	//	cout << "debug:=" << Point[PII(yy, xx)] << endl;
	//}


	return 0;
}
accuracy: 1
time_ms: 360
memory_kb: 12060
final_rank: 4

code_snippet: // AOJ #3005 Great Devil Sakanikia
// 2025.3.21

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

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

struct UnionFind {
    vector<int> par, rank;
    UnionFind(int n) : par(n), rank(n, 0) {
        for (int i = 0; i < n; i++) par[i] = i;
    }
    int find(int x) {
        return par[x] = (par[x] == x ? x : find(par[x]));
    }
    void unite(int x, int y) {
        x = find(x), y = find(y);
        if(x == y) return;
        if(rank[x] < rank[y]) swap(x, y);
        par[y] = x;
        if(rank[x] == rank[y]) rank[x]++;
    }
    bool same(int x, int y) { return find(x) == find(y); }
};

struct PairHash {
    size_t operator()(const pair<int,int>& p) const {
        return ((size_t)p.first * 13131ULL) ^ ((unsigned int)p.second);
    }
};

inline bool inRange(int v, int lim) {
    return 0 <= v && v < lim;
}

int dy8[8] = { -1, -1, -1, 0, 1, 1, 1, 0 };
int dx8[8] = { -1,  0,  1, 1, 1, 0, -1, -1 };

int dy16[16] = { -2, -2, -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1 };
int dx16[16] = { -2, -1,  0,  1,  2,  2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2 };

int solve(){
    int H = Cin(), W = Cin(), k = Cin();
    vector<pair<int,int>> obs(k);
    for (int i = 0; i < k; i++){
        int x = Cin(), y = Cin();
        obs[i] = { y, x };
    }
    unordered_map<pair<int,int>, int, PairHash> obst;
    obst.reserve(k * 2);
    for (int i = 0; i < k; i++) obst[ obs[i] ] = i;

    int extra = 2;
    int total = k + extra;
    int groupA = k;
    int groupB = k+1;
    UnionFind uf(total);

    for (int i = 0; i < k; i++){
        int y = obs[i].first, x = obs[i].second;
        for (int d = 0; d < 8; d++){
            int ny = y + dy8[d], nx = x + dx8[d];
            if (!inRange(ny, W) || !inRange(nx, H)) {
                if (ny < 0) uf.unite(i, groupA);
                if (nx < 0) uf.unite(i, groupB);
                if (ny >= W) uf.unite(i, groupB);
                if (nx >= H) uf.unite(i, groupA);
            } else {
                pair<int,int> np = { ny, nx };
                if (obst.find(np) != obst.end()) uf.unite(i, obst[np]);
            }
        }
    }

    if (uf.same(groupA, groupB)) return 0;

    for (int i = 0; i < k; i++){
        if (!uf.same(i, groupA) && !uf.same(i, groupB)) continue;
        int join = uf.same(i, groupB) ? 1 : 0;
        int targetGroup = (join == 1 ? groupA : groupB);
        for (int d = 0; d < 16; d++){
            int ny = obs[i].first + dy16[d], nx = obs[i].second + dx16[d];
            if (!inRange(ny, W) || !inRange(nx, H)) {
                if ((ny < 0 && join == 1) || (nx < 0 && join == 0) ||
                    (ny >= W && join == 0) || (nx >= H && join == 1)) return 1;
            } else {
                pair<int,int> np = { ny, nx };
                if (obst.find(np) == obst.end()) continue;
                if (uf.same(obst[np], targetGroup)) return 1;
            }
        }
    }
    return 2;
}

int main() {
    pc('0'+solve()), pc('\n');
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 10880
final_rank: 1

code_snippet: // AOJ #3005 Great Devil Sakanikia
// 2025.3.21

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

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0; int c = gc();
	if (c == '-') {	c = gc();
		do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
		return -n;
	}
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

struct UnionFind {
    vector<int> par, rank;
    UnionFind(int n) : par(n), rank(n, 0) {
        for (int i = 0; i < n; i++) par[i] = i;
    }
    int find(int x) {
        return par[x] = (par[x] == x ? x : find(par[x]));
    }
    void unite(int x, int y) {
        x = find(x), y = find(y);
        if(x == y) return;
        if(rank[x] < rank[y]) swap(x, y);
        par[y] = x;
        if(rank[x] == rank[y]) rank[x]++;
    }
    bool same(int x, int y) { return find(x) == find(y); }
};

struct PairHash {
    size_t operator()(const pair<int,int>& p) const {
        return ((size_t)p.first * 13131ULL) ^ ((unsigned int)p.second);
    }
};

inline bool inRange(int v, int lim) {
    return 0 <= v && v < lim;
}

int dy8[8] = { -1, -1, -1, 0, 1, 1, 1, 0 };
int dx8[8] = { -1,  0,  1, 1, 1, 0, -1, -1 };

int dy16[16] = { -2, -2, -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1 };
int dx16[16] = { -2, -1,  0,  1,  2,  2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2 };

int main(){
    int n = Cin(), m = Cin(), k = Cin();
    vector<pair<int,int>> obs(k);
    for (int i = 0; i < k; i++){
        int x = Cin(), y = Cin();
        obs[i] = { x, y };
    }
    unordered_map<pair<int,int>, int, PairHash> obst;
    obst.reserve(k * 2);
    for (int i = 0; i < k; i++) obst[ obs[i] ] = i;

    int extra = 2;
    int total = k + extra;
    int groupA = k;
    int groupB = k+1;
    UnionFind uf(total);

    for (int i = 0; i < k; i++){
        int y = obs[i].first, x = obs[i].second;
        for (int d = 0; d < 8; d++){
            int ny = y + dy8[d], nx = x + dx8[d];
            if (!inRange(ny, n) || !inRange(nx, m)) {
                if (ny < 0) uf.unite(i, groupA);
                if (nx < 0) uf.unite(i, groupB);
                if (ny >= n) uf.unite(i, groupB);
                if (nx >= m) uf.unite(i, groupA);
            } else {
                pair<int,int> np = { ny, nx };
                if (obst.find(np) != obst.end()){
                    uf.unite(i, obst[np]);
                }
            }
        }
    }

    if (uf.same(groupA, groupB)){
        pc('0'), pc('\n');
        return 0;
    }

    for (int i = 0; i < k; i++){
        if (!uf.same(i, groupA) && !uf.same(i, groupB)) continue;
        int join = uf.same(i, groupB) ? 1 : 0;
        int targetGroup = (join == 1 ? groupA : groupB);
        for (int d = 0; d < 16; d++){
            int ny = obs[i].first + dy16[d], nx = obs[i].second + dx16[d];
            if (!inRange(ny, n) || !inRange(nx, m)) {
                if ((ny < 0 && join == 1) || (nx < 0 && join == 0) ||
                    (ny >= n && join == 0) || (nx >= m && join == 1)) {
                    pc('1'), pc('\n');
                    return 0;
                }
            } else {
                pair<int,int> np = { ny, nx };
                if (obst.find(np) == obst.end()) continue;
                if (uf.same(obst[np], targetGroup)){
                    pc('1'), pc('\n');
                    return 0;
                }
            }
        }
    }
    pc('2'), pc('\n');
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 10908
final_rank: 2

code_snippet: #include <algorithm>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
#define MOD 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
int n, m, k;
int x[100001], y[100001];
map<ll, int> g;
int cost[100001];
int bfs() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 1; i <= m - 1; i++) {
    ll val = (ll)i * n;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (nx < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny < 0 || nx >= n) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (nx < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny < 0 || nx >= n)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs2() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 1; i <= n - 1; i++) {
    ll val = i;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (ny < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx < 0 || ny >= m) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (ny < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx < 0 || ny >= m)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs3() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 0; i <= n - 2; i++) {
    ll val = (ll)n * (m - 1) + i;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (ny >= m)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx >= n || ny < 0) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (ny >= m)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx >= n || ny < 0)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs4() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 0; i <= m - 2; i++) {
    ll val = (ll)i * n + n - 1;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (nx >= n)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny >= m || nx < 0) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (nx >= n)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny >= m || nx < 0)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int main(void) {
  scanf("%d%d%d", &n, &m, &k);
  for (int i = 0; i < k; i++) {
    scanf("%d%d", &x[i], &y[i]);
    g[(ll)y[i] * n + x[i]] = i;
  }
  int res = 2;
  res = min(res, bfs());
  res = min(res, bfs2());
  res = min(res, bfs3());
  res = min(res, bfs4());
  printf("%d\n", res);
  return 0;
}
accuracy: 1
time_ms: 1270
memory_kb: 10792
final_rank: 14

code_snippet: #include <algorithm>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
#define MOD 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
int n, m, k;
int x[100001], y[100001];
map<ll, int> g;
int cost[100001];
int bfs() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 1; i <= m - 1; i++) {
    ll val = (ll)i * n;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (nx < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny < 0 || nx >= n) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (nx < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny < 0 || nx >= n)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs2() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 1; i <= n - 1; i++) {
    ll val = i;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (ny < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx < 0 || ny >= m) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (ny < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx < 0 || ny >= m)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs3() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 0; i <= n - 2; i++) {
    ll val = (ll)n * (m - 1) + i;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (ny >= m)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx >= n || ny < 0) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (ny >= m)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx >= n || ny < 0)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs4() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 0; i <= m - 2; i++) {
    ll val = (ll)i * n + n - 1;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (nx >= n)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny >= m || nx < 0) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (nx >= n)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny >= m || nx < 0)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int main(void) {
  scanf("%d%d%d", &n, &m, &k);
  for (int i = 0; i < k; i++) {
    scanf("%d%d", &x[i], &y[i]);
    g[(ll)y[i] * n + x[i]] = i;
  }
  int res = 2;
  res = min(res, bfs());
  if (g.size() != k)
    return 0;
  res = min(res, bfs2());
  res = min(res, bfs3());
  res = min(res, bfs4());
  printf("%d\n", res);
  return 0;
}
accuracy: 1
time_ms: 1200
memory_kb: 10840
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#define MOD 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
int n, m, k;
int x[100001], y[100001];
map<ll, int> g;
int cost[100001];
int bfs() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 1; i <= m - 1; i++) {
    ll val = (ll)i * n;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (nx < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny < 0 || nx >= n) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (nx < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny < 0 || nx >= n)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs2() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 1; i <= n - 1; i++) {
    ll val = i;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (ny < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx < 0 || ny >= m) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (ny < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx < 0 || ny >= m)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs3() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 0; i <= n - 2; i++) {
    ll val = (ll)n * (m - 1) + i;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (ny >= m)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx >= n || ny < 0) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (ny >= m)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx >= n || ny < 0)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs4() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 0; i <= m - 2; i++) {
    ll val = (ll)i * n + n - 1;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (nx >= n)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny >= m || nx < 0) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (nx >= n)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny >= m || nx < 0)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int main(void) {
  scanf("%d%d%d", &n, &m, &k);
  for (int i = 0; i < k; i++) {
    scanf("%d%d", &x[i], &y[i]);
    g[(ll)y[i] * n + x[i]] = i;
  }
  int res = 2;
  res = min(res, bfs());
  res = min(res, bfs2());
  res = min(res, bfs3());
  res = min(res, bfs4());
  printf("%d\n", res);
  return 0;
}
accuracy: 1
time_ms: 1230
memory_kb: 10856
final_rank: 12

code_snippet: #include <algorithm>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
#define MOD 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
int n, m, k;
int x[100001], y[100001];
map<ll, int> g;
int cost[100001];
int bfs() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 1; i <= m - 1; i++) {
    ll val = (ll)i * n;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (nx < 0)
          continue;
        if (ny < 0 || nx >= n) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (nx < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny < 0 || nx >= n)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs2() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 1; i <= n - 1; i++) {
    ll val = i;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (ny < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx < 0 || ny >= m) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (ny < 0)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx < 0 || ny >= m)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs3() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 0; i <= n - 2; i++) {
    ll val = (ll)n * (m - 1) + i;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (ny >= m)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx >= n || ny < 0) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (ny >= m)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (nx >= n || ny < 0)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int bfs4() {
  queue<int> que;
  queue<int> que2;
  bool flag = false;
  memset(cost, -1, sizeof(cost));
  for (int i = 0; i <= m - 2; i++) {
    ll val = (ll)i * n + n - 1;
    if (g.find(val) != g.end()) {
      que.push(g[val]);
      cost[g[val]] = 0;
    }
  }
  while (que.size()) {
    int q = que.front();
    que.pop();
    for (int i = -2; i <= 2; i++) {
      for (int j = -2; j <= 2; j++) {
        int nc = 0;
        if (abs(i) > 1 || abs(j) > 1)
          nc = 1;
        int nx = j + x[q], ny = i + y[q];
        if (nx >= n)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny >= m || nx < 0) {
          if (nc == 0)
            return 0;
          if (nc == 1)
            flag = true;
        }
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = nc;
              if (nc == 0)
                que.push(g[nval]);
              if (nc == 1)
                que2.push(g[nval]);
            } else if (cost[g[nval]] == 1 && nc == 0) {
              cost[g[nval]] = 0;
              que.push(g[nval]);
            }
          }
        }
      }
    }
  }
  if (flag)
    return 1;
  while (que2.size()) {
    int q = que2.front();
    que2.pop();
    for (int i = -1; i <= 1; i++) {
      for (int j = -1; j <= 1; j++) {
        int nc = 0;
        int nx = j + x[q], ny = i + y[q];
        if (nx >= n)
          continue;
        if (nx == 0 && ny == 0)
          continue;
        if (nx == n - 1 && ny == m - 1)
          continue;
        if (ny >= m || nx < 0)
          return 1;
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
          ll nval = (ll)ny * n + nx;
          if (g.find(nval) != g.end()) {
            if (cost[g[nval]] == -1) {
              cost[g[nval]] = 1;
              que2.push(g[nval]);
            }
          }
        }
      }
    }
  }
  return 2;
}
int main(void) {
  scanf("%d%d%d", &n, &m, &k);
  for (int i = 0; i < k; i++) {
    scanf("%d%d", &x[i], &y[i]);
    g[(ll)y[i] * n + x[i]] = i;
  }
  int res = 2;
  res = min(res, bfs());
  res = min(res, bfs2());
  res = min(res, bfs3());
  res = min(res, bfs4());
  printf("%d\n", res);
  return 0;
}
accuracy: 1
time_ms: 1240
memory_kb: 10860
final_rank: 13

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 100005

typedef pair<int,int> P;

int W,H;
int K,num_Cell;
int diff_row[8] = {-1,-1,-1,0,0,1,1,1},diff_col[8] = {-1,0,1,-1,1,-1,0,1};
int boss[6*SIZE],height[6*SIZE];
map<P,bool> MAP;
map<P,int> ID;
vector<P> V,LEFT_UP,RIGHT_UNDER,CANDIDATE;


bool rangeCheck(int row,int col){

    return row >= 0 && row <= H+1 && col >= 0 && col <= W+1;
}

int get_boss(int id){
    if(boss[id] == id)return id;
    else{
        return boss[id] = get_boss(boss[id]);
    }
}

void unite(int x,int y){
    int boss_x = get_boss(x);
    int boss_y = get_boss(y);

    if(boss_x == boss_y)return;

    //高さが高い方に吸収する
    if(height[x] > height[y]){

        boss[boss_y] = boss_x;

    }else if(height[x] < height[y]){

        boss[boss_x] = boss_y;

    }else{ //height[x] == height[y]

        boss[boss_y] = boss_x;
        height[x]++;
    }
}

int main(){

    scanf("%d %d %d",&W,&H,&K);

    num_Cell = 0;

    int x,y;

    for(int loop = 0; loop < K; loop++){

        scanf("%d %d",&x,&y);
        //外側をダミーセルで覆う
        x++;
        y++;

        MAP[make_pair(x,y)] = true;
        ID[make_pair(x,y)] = num_Cell++;
        V.push_back(make_pair(x,y));
    }

    //猫を左下に見た時、左上方向のダミーセルを列挙する
    for(int x = 0; x <= W-2; x++){

        MAP[make_pair(x,H+1)] = true;
        ID[make_pair(x,H+1)] = num_Cell++;
        LEFT_UP.push_back(make_pair(x,H+1));
    }
    for(int y = H; y >= 3; y--){

        MAP[make_pair(0,y)] = true;
        ID[make_pair(0,y)] = num_Cell++;
        LEFT_UP.push_back(make_pair(0,y));
    }

    //右下方向
    for(int y = 0; y <= H-2; y++){

        MAP[make_pair(W+1,y)] = true;
        ID[make_pair(W+1,y)] = num_Cell++;
        RIGHT_UNDER.push_back(make_pair(W+1,y));
    }
    for(int x = 3; x <= W; x++){

        MAP[make_pair(x,0)] = true;
        ID[make_pair(x,0)] = num_Cell++;
        RIGHT_UNDER.push_back(make_pair(x,0));
    }

    for(int i = 0; i < num_Cell; i++){

        boss[i] = i;
        height[i] = 0;
    }

    //左上方向のダミーセルの連結
    for(int i = 1; i < LEFT_UP.size(); i++){

        int left_id = ID[LEFT_UP[i-1]];
        int right_id = ID[LEFT_UP[i]];
        unite(left_id,right_id);
    }

    //右下方向のダミーセルの連結
    for(int i = 1; i < RIGHT_UNDER.size(); i++){

        int left_id = ID[RIGHT_UNDER[i-1]];
        int right_id = ID[RIGHT_UNDER[i]];
        unite(left_id,right_id);
    }

    //実セルの連結
    for(int i = 0; i < V.size(); i++){
        for(int a = 0; a < 8; a++){

            int adj_row = V[i].second+diff_row[a];
            int adj_col = V[i].first+diff_col[a];

            auto at = MAP.find(make_pair(adj_col,adj_row));

            if(at == MAP.end())continue;

            int my_id = ID[V[i]];
            int adj_id = ID[make_pair(adj_col,adj_row)];

            unite(my_id,adj_id);
        }
    }

    int LEFT_UP_id = ID[make_pair(0,H+1)];
    int RIGHT_UNDER_id = ID[make_pair(W+1,0)];

    if(get_boss(LEFT_UP_id) == get_boss(RIGHT_UNDER_id)){ //最初から遮断されている場合

        printf("0\n");
        return 0;
    }

    //追加1つで遮断できるか調べる
    for(int i = 0; i < V.size(); i++){
        for(int a = 0; a < 8; a++){

            int adj_row = V[i].second+diff_row[a];
            int adj_col = V[i].first+diff_col[a];

            auto at = MAP.find(make_pair(adj_col,adj_row));

            if(at != MAP.end())continue; //ダミーセル、または岩が既に置いてあったらSKIP

            CANDIDATE.push_back(make_pair(adj_col,adj_row)); //架空のセル
        }
    }

    sort(CANDIDATE.begin(),CANDIDATE.end());
    CANDIDATE.erase(unique(CANDIDATE.begin(),CANDIDATE.end()),CANDIDATE.end());

    for(int i = 0; i < CANDIDATE.size(); i++){

        bool FLG_LU = false,FLG_RD = false;

        for(int a = 0; a < 8; a++){

            int adj_row = CANDIDATE[i].second+diff_row[a];
            int adj_col = CANDIDATE[i].first+diff_col[a];

            if(!rangeCheck(adj_row,adj_col))continue;

            auto at = MAP.find(make_pair(adj_col,adj_row));

            if(at == MAP.end())continue;

            int adj_id = ID[make_pair(adj_col,adj_row)];


            if(get_boss(adj_id) == get_boss(LEFT_UP_id)){

                FLG_LU = true;

            }else if(get_boss(adj_id) == get_boss(RIGHT_UNDER_id)){

                FLG_RD = true;
            }
        }

        if(FLG_LU && FLG_RD){
            printf("1\n");
            return 0;
        }
    }

    printf("2\n");

    return 0;
}
accuracy: 1
time_ms: 900
memory_kb: 81532
final_rank: 17

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 100005

typedef pair<int,int> P;

int W,H;
int K,num_Cell;
int diff_row[8] = {-1,-1,-1,0,0,1,1,1},diff_col[8] = {-1,0,1,-1,1,-1,0,1};
int boss[6*SIZE],height[6*SIZE];
map<P,bool> MAP;
map<P,int> ID;
vector<P> V,LEFT_UP,RIGHT_UNDER,CANDIDATE;


bool rangeCheck(int row,int col){

    return row >= 0 && row <= H+1 && col >= 0 && col <= W+1;
}

int get_boss(int id){
    if(boss[id] == id)return id;
    else{
        return boss[id] = get_boss(boss[id]);
    }
}

void unite(int x,int y){
    int boss_x = get_boss(x);
    int boss_y = get_boss(y);

    if(boss_x == boss_y)return;

    //高さが高い方に吸収する
    if(height[x] > height[y]){

        boss[boss_y] = boss_x;

    }else if(height[x] < height[y]){

        boss[boss_x] = boss_y;

    }else{ //height[x] == height[y]

        boss[boss_y] = boss_x;
        height[x]++;
    }
}

int main(){

    scanf("%d %d %d",&W,&H,&K);

    num_Cell = 0;

    int x,y;

    for(int loop = 0; loop < K; loop++){

        scanf("%d %d",&x,&y);
        //外側をダミーセルで覆う
        x++;
        y++;

        MAP[make_pair(x,y)] = true;
        ID[make_pair(x,y)] = num_Cell++;
        V.push_back(make_pair(x,y));
    }

    //猫を左下に見た時、左上方向のダミーセルを列挙する
    for(int x = 0; x <= W-2; x++){

        MAP[make_pair(x,H+1)] = true;
        ID[make_pair(x,H+1)] = num_Cell++;
        LEFT_UP.push_back(make_pair(x,H+1));
    }
    for(int y = H; y >= 3; y--){

        MAP[make_pair(0,y)] = true;
        ID[make_pair(0,y)] = num_Cell++;
        LEFT_UP.push_back(make_pair(0,y));
    }

    //右下方向
    for(int y = 0; y <= H-2; y++){

        MAP[make_pair(W+1,y)] = true;
        ID[make_pair(W+1,y)] = num_Cell++;
        RIGHT_UNDER.push_back(make_pair(W+1,y));
    }
    for(int x = 3; x <= W; x++){

        MAP[make_pair(x,0)] = true;
        ID[make_pair(x,0)] = num_Cell++;
        RIGHT_UNDER.push_back(make_pair(x,0));
    }

    for(int i = 0; i < num_Cell; i++){

        boss[i] = i;
        height[i] = 0;
    }

    //左上方向のダミーセルの連結
    for(int i = 1; i < LEFT_UP.size(); i++){

        int left_id = ID[LEFT_UP[i-1]];
        int right_id = ID[LEFT_UP[i]];
        unite(left_id,right_id);
    }

    //右下方向のダミーセルの連結
    for(int i = 1; i < RIGHT_UNDER.size(); i++){

        int left_id = ID[RIGHT_UNDER[i-1]];
        int right_id = ID[RIGHT_UNDER[i]];
        unite(left_id,right_id);
    }

    //実セルの連結
    for(int i = 0; i < V.size(); i++){
        for(int a = 0; a < 8; a++){

            int adj_row = V[i].second+diff_row[a];
            int adj_col = V[i].first+diff_col[a];

            auto at = MAP.find(make_pair(adj_col,adj_row));

            if(at == MAP.end())continue;

            int my_id = ID[V[i]];
            int adj_id = ID[make_pair(adj_col,adj_row)];

            unite(my_id,adj_id);
        }
    }

    int num_group = 0;

    for(int i = 0; i < num_Cell; i++){

        if(i == get_boss(i)){
            num_group++;
        }
    }

    if(num_group == 1){ //最初から遮断されている場合

        printf("0\n");
        return 0;
    }


    //追加1つで遮断できるか調べる
    for(int i = 0; i < V.size(); i++){
        for(int a = 0; a < 8; a++){

            int adj_row = V[i].second+diff_row[a];
            int adj_col = V[i].first+diff_col[a];

            auto at = MAP.find(make_pair(adj_col,adj_row));

            if(at != MAP.end())continue; //ダミーセル、または岩が既に置いてあったらSKIP

            CANDIDATE.push_back(make_pair(adj_col,adj_row)); //架空のセル
        }
    }

    sort(CANDIDATE.begin(),CANDIDATE.end());
    CANDIDATE.erase(unique(CANDIDATE.begin(),CANDIDATE.end()),CANDIDATE.end());

    for(int i = 0; i < CANDIDATE.size(); i++){

        bool FLG_LU = false,FLG_RD = false;

        for(int a = 0; a < 8; a++){

            int adj_row = CANDIDATE[i].second+diff_row[a];
            int adj_col = CANDIDATE[i].first+diff_col[a];

            if(!rangeCheck(adj_row,adj_col))continue;

            auto at = MAP.find(make_pair(adj_col,adj_row));

            if(at == MAP.end())continue;

            int adj_id = ID[make_pair(adj_col,adj_row)];
            int LEFT_UP_id = ID[make_pair(0,H+1)];
            int RIGHT_UNDER_id = ID[make_pair(W+1,0)];

            if(get_boss(adj_id) == get_boss(LEFT_UP_id)){

                FLG_LU = true;

            }else if(get_boss(adj_id) == get_boss(RIGHT_UNDER_id)){

                FLG_RD = true;
            }
        }

        if(FLG_LU && FLG_RD){
            printf("1\n");
            return 0;
        }
    }

    printf("2\n");

    return 0;
}
accuracy: 0.8157894736842105
time_ms: 960
memory_kb: 81484
final_rank: 19

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<utility>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
const ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int> P;
typedef pair<ll, ll> LP;
typedef vector<int> vec;
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define stop char nyaa;cin>>nyaa;

struct uf {
private:
	vector<int> par, ran;
public:
	uf(int n) {
		par.resize(n, 0);
		ran.resize(n, 0);
		rep(i, n)par[i] = i;
	}
	int find(int x) {
		if (par[x] == x)return x;
		else return par[x] = find(par[x]);
	}
	void unite(int x, int y) {
		x = find(x), y = find(y);
		if (x == y)return;
		if (ran[x] < ran[y]) {
			par[x] = y;
		}
		else {
			par[y] = x;
			if (ran[x] == ran[y])ran[x]++;
		}
	}
	bool same(int x, int y) {
		return find(x) == find(y);
	}
};
map<P, int> mp;
void solve() {
	int h, w; cin >> h >> w;
	int n; cin >> n;
	vector<P> v(n);
	rep(i, n) {
		cin >> v[i].first >> v[i].second;
		mp[v[i]] = i + 1;
	}
	uf u(n + 2);
	int le = n, ri = n + 1;
	rep(i, n) {
		if (v[i].first == h - 1 || v[i].second == 0) {
			u.unite(le, i);
		}
		if (v[i].first == 0 || v[i].second == w - 1) {
			u.unite(i, ri);
		}
		for (int j = -1; j <= 1; j++) {
			for (int k = -1; k <= 1; k++) {
				int nx = j + v[i].first, ny = k + v[i].second;
				int z = mp[{nx, ny}];
				if (z > 0) {
					z--;
					u.unite(i, z);
				}
			}
		}
	}
	if (u.same(le, ri)) {
		cout << 0 << endl; return;
	}
	rep(i, n) {
		if (u.same(le, i)) {
			if (v[i].first == 1 || v[i].second == w - 2) {
				cout << 1 << endl; return;
			}
			for (int j = -2; j <= 2; j++) {
				for (int k = -2; k <= 2; k++) {
					int nx = j + v[i].first, ny = k + v[i].second;
					int z = mp[{nx, ny}];
					if (z > 0) {
						z--;
						if (u.same(z, ri)) {
							cout << 1 << endl; return;
						}
					}
				}
			}
		}
		else if (u.same(i, ri)) {
			if (v[i].first == h - 2 || v[i].second == 1) {
				cout << 1 << endl; return;
			}
			for (int j = -2; j <= 2; j++) {
				for (int k = -2; k <= 2; k++) {
					int nx = j + v[i].first, ny = k + v[i].second;
					int z = mp[{nx, ny}];
					if (z > 0) {
						z--;
						if (u.same(z, le)) {
							cout << 1 << endl; return;
						}
					}
				}
			}
		}
	}
	cout << 2 << endl;
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	solve();
	//stop
		return 0;
}
accuracy: 1
time_ms: 420
memory_kb: 60556
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

const int dx[8]={1,1,0,-1,-1,-1,0,1};
const int dy[8]={0,-1,-1,-1,0,1,1,1};

using pi = pair<int,int>;

int solve(){
    int w,h,k;
    cin >>w >>h >>k;

    vector<pi> p(k);
    map<pi,int> m;
    rep(i,k){
        int x,y;
        scanf(" %d %d", &x, &y);
        p[i] = {y,x};
        m[p[i]] = i;
    }

    auto IN = [&](int y, int x){
        return 0<=y && y<h && 0<=x && x<w;
    };

    auto isS = [&](pi t){
        if(t.fi == h-1) return t.se != w-1;
        if(t.se == 0) return t.fi != 0;
        return false;
    };

    auto isT = [&](pi t){
        if(t.fi == 0) return t.se != 0;
        if(t.se == w-1) return t.fi != h-1;
        return false;
    };

    queue<int> que;

    vector<bool> viss(k);
    rep(i,k){
        if(isS(p[i])){
            viss[i] = true;
            que.push(i);
        }
    }
    while(!que.empty()){
        int now = que.front();
        que.pop();
        rep(i,8){
            int ny = p[now].fi+dy[i], nx = p[now].se+dx[i];
            if(!IN(ny,nx)) continue;

            if(m.count({ny,nx})){
                int idx = m[{ny,nx}];
                if(!viss[idx]){
                    viss[idx] = true;
                    que.push(idx);
                }
            }
        }
    }

    vector<bool> vist(k);
    rep(i,k){
        if(isT(p[i])){
            vist[i] = true;
            que.push(i);
        }
    }
    while(!que.empty()){
        int now = que.front();
        que.pop();
        rep(i,8){
            int ny = p[now].fi+dy[i], nx = p[now].se+dx[i];
            if(!IN(ny,nx)) continue;

            if(m.count({ny,nx})){
                int idx = m[{ny,nx}];
                if(!vist[idx]){
                    vist[idx] = true;
                    que.push(idx);
                }
            }
        }
    }

    rep(i,k)if(viss[i] && vist[i]) return 0;

    rep(i,k)rep(j,8){
        int ny = p[i].fi+dy[j], nx = p[i].se+dx[j];
        if(!IN(ny,nx)) continue;

        bool ss = false, tt = false;
        rep(d,8){
            int Y = ny+dy[d], X = nx+dx[d];
            if(!IN(Y,X)) continue;
            if(m.count({Y,X})){
                int idx = m[{Y,X}];
                if(viss[idx]) ss = true;
                if(vist[idx]) tt = true;
            }
        }
        if(ss && tt) return 1;

        if(viss[i] && isT({ny,nx})) return 1;
        if(vist[i] && isS({ny,nx})) return 1;
    }

    return 2;
}

int main(){
    cout << solve() << endl;
    return 0;
}
accuracy: 1
time_ms: 650
memory_kb: 10008
final_rank: 8

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

using VS = vector<string>;    using LL = long long;
using VI = vector<int>;       using VVI = vector<VI>;
using PII = pair<int, int>;   using PLL = pair<LL, LL>;
using VL = vector<LL>;        using VVL = vector<VL>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))
#define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++)
#define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--)
#define debug(x) cerr << #x << ": " << x << endl
const int INF = 1e9;                          const LL LINF = 1e16;
const LL MOD = 1000000007;                    const double PI = acos(-1.0);
int DX[8] = { 0, 0, 1, -1, 1, 1, -1, -1 };    int DY[8] = { 1, -1, 0, 0, 1, -1, 1, -1 };

/* -----  2018/07/05  Problem: AOJ 3005 / Link: https://onlinejudge.u-aizu.ac.jp/challenges/search/volumes/3005  ----- */
/* ------問題------



-----問題ここまで----- */
/* -----解説等-----



----解説ここまで---- */


struct UnionFind {
	vector<int> data;
	UnionFind(int n) { data.assign(n, -1); }
	bool unionSet(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	bool same(int x, int y) { return root(x) == root(y); }
	int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
	int size(int x) { return -data[root(x)]; }
};
// UnionFind uf(n); uf.unionSet(i,j); if(uf.same(x,y))
#define IN(a, x, b) (a<=x && x<b)


int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);

	int H, W, K;
	cin >> W >> H >> K;
	map<PII, int>Point;
	VI x(K), y(K);
	int pc =1;
	FOR(i, 0, K) {
		cin >> x[i] >> y[i];
		Point[PII(y[i], x[i])] = pc++;
	}

	// uf
	UnionFind uf(K + 2 * (H + W));
	int A = pc++;
	int B = pc++;

	FOR(i, 0, K) {
		FOR(d, 0, 8) {
			int ny = y[i] + DY[d];
			int nx = x[i] + DX[d];
			if (!IN(0, nx, W) || !IN(0, ny, H)) {
				if (ny < 0) uf.unionSet(Point[PII(y[i], x[i])], A);
				if (nx < 0) uf.unionSet(Point[PII(y[i], x[i])], B);
				if (ny > H - 1) uf.unionSet(Point[PII(y[i], x[i])], B);
				if (nx > W - 1) uf.unionSet(Point[PII(y[i], x[i])], A);
			}
			else {
				if (Point.find(PII(ny, nx)) == Point.end()) continue;
				uf.unionSet(Point[PII(y[i],x[i])], Point[PII(ny, nx)]);
			}
		}
	}
	if (uf.same(A, B)) {
		cout << "0" << endl;
	}
	else {
		int f = 0;
		int dy[] = { -2,-2,-2,-2,-2,-1,0,1,2,2,2,2,2,1,0,-1 };
		int dx[] = { -2,-1,0,1,2,2,2,2,2,1,0,-1,-2,-2,-2,-2 };
		FOR(i, 0, K) {
			if (!uf.same(Point[PII(y[i], x[i])], A) && !uf.same(Point[PII(y[i], x[i])], B)) continue;
			int join = uf.same(Point[PII(y[i], x[i])], B);
			FOR(d, 0, 16) {
				int ny = y[i] + dy[d];
				int nx = x[i] + dx[d];
				if (!IN(0, nx, W) || !IN(0, ny, H)) {
					if ((ny < 0 && join == 1) ||
						(nx < 0 && join == 0) ||
						(ny > H - 1 && join == 0) ||
						(nx > W - 1 && join == 1)){
						f = 1;
					}
				}
				else {
					if (Point.find(PII(ny, nx)) == Point.end()) continue;
					if (uf.same(Point[PII(ny, nx)], A + !join)) {
						f = 1;
					}
				}
			}
		}
		cout << (f ? 1 : 2) << endl;
	}
	//debug(A);
	//debug(B);
	//int yy, xx;
	//while (cin >> yy >> xx) {
	//	cout << "debug:=" << Point[PII(yy, xx)] << endl;
	//}


	return 0;
}//
accuracy: 1
time_ms: 300
memory_kb: 11720
final_rank: 3

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

typedef pair<int,int> P;

int w, h, k, ans=2;
set<P> exist;
set<P> visited[2];

void bfs(vector<P> s, int idx){
  
  queue<P> q;
  
  for(int i=0;i<s.size();i++){
    q.push(s[i]);
    visited[idx].insert(s[i]);
  }
  
  while(!q.empty()){
    
    P node=q.front(); q.pop();
    int x=node.first, y=node.second;
    
    if(idx==0){
      if(x==w-1||y==0) ans=min(ans, 0);
      if(x==w-2||y==1) ans=min(ans, 1);
    }
    
    if(idx==1){
      if(x==0||y==h-1) ans=min(ans, 0);
      if(x==1||y==h-2) ans=min(ans, 1);
    }
    
    for(int i=-1;i<=1;i++){
      for(int j=-1;j<=1;j++){
	
	if(i==0&&j==0) continue;
	
	int nx=x+i, ny=y+j;
      
	if(nx<0||ny<0||w<=nx||h<=ny) continue;
      
	if(exist.count(P(nx,ny))==0) continue;
	if(visited[idx].count(P(nx,ny))==1) continue;
      
	q.push(P(nx,ny));
	visited[idx].insert(P(nx,ny));
      }
    }
    
    if(idx==1){
      
      for(int i=-1;i<=1;i++){
	for(int j=-1;j<=1;j++){
	  
	  if(i==0&&j==0) continue;
	  
	  int nx=x+i, ny=y+j;
	  if(nx<0||ny<0||w<=nx||h<=ny) continue;
	  
	  for(int k=-1;k<=1;k++){
	    for(int l=-1;l<=1;l++){

	      if(k==0&&l==0) continue;
	      
	      if(!(i+k==-2||i+k==2||j+l==-2||j+l==2)) continue;
	      
	      int nnx=nx+k, nny=ny+l;
	  
	      if(nnx<0||nny<0||w<=nnx||h<=nny) continue;
	  
	      if(abs(x-nnx)+abs(y-nny)<=1) continue;
	  
	      if(visited[0].count(P(nnx,nny))==1) ans=min(ans, 1);
	      
	    }
	  }
	  
	}
	
      }
	
    }
  }
  
}

int main(){
  
  cin>>w>>h>>k;
  
  int x, y;
  vector<P> s1, s2;
    
  for(int i=0;i<k;i++){
    scanf("%d %d", &x, &y);
    if(x==0||y==h-1) s1.push_back(P(x,y));
    if(x==w-1||y==0) s2.push_back(P(x,y));
    exist.insert(P(x,y));
  }
  
  bfs(s1, 0);
  
  bfs(s2, 1);
  
  cout<<ans<<endl;
  
  return 0;
}
accuracy: 1
time_ms: 440
memory_kb: 17268
final_rank: 6

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;

//// < "d:\d_download\visual studio 2015\projects\programing_contest_c++\debug\a.txt" > "d:\d_download\visual studio 2015\projects\programing_contest_c++\debug\b.txt"

int dx8[8] = { -1,-1,-1, 0, 1, 1, 1, 0 };
int dy8[8] = { -1, 0, 1, 1, 1, 0,-1,-1 };

struct aaa {
	int nx;
	int ny;
	int cost;
};

int main() {
	int W, H, K; cin >> W >> H >> K;
	set<pair<int, int>>obset;
	for (int i = 0; i < K; ++i) {
		int a, b; cin >> a >> b;
		obset.emplace(a, b);
	}
	map<pair<int, int>, int>mp;
	deque<aaa>que;
	for (int x = 0; x < W; ++x) {
		mp[make_pair(x, -1)] = 0;
		que.push_back(aaa{ x,-1,0 });
	}
	for (int y = 0; y < H; ++y) {
		mp[make_pair(W,y)] = 0;
		que.push_back(aaa{ W,y,0 });
	}
	int ans = 2;
	while (!que.empty()) {
		auto aa(que.front());
		que.pop_front();
		if (aa.nx == 0 && aa.ny >0) {
			ans = aa.cost;
			break;
		}
		else if (aa.nx < W - 1 && aa.ny ==H-1) {
			ans = aa.cost;
			break;
		}
		for (int way = 0; way < 8; ++way) {
			int nextx = aa.nx + dx8[way];
			int nexty = aa.ny + dy8[way];
			if (nextx >= 0 && nextx < W&&nexty >= 0 && nexty < H) {
				if (nextx == 0 && nexty == 0)continue;
				if (nextx == W - 1 && nexty == H - 1)continue;
				int nextcost = aa.cost;
				bool flag = false;
				if (obset.find(make_pair(nextx, nexty)) == obset.end()) {
					nextcost++;
					flag = true;
				}
				if (nextcost >= 2)continue;
				if (mp.find(make_pair(nextx, nexty)) == mp.end()) {
					mp[make_pair(nextx, nexty)] = 3;
				}
				if (mp[make_pair(nextx, nexty)] > nextcost) {
					mp[make_pair(nextx, nexty)] = nextcost;
					if (flag) {
						que.push_back(aaa{ nextx,nexty,nextcost });
					}
					else {
						que.push_front(aaa{ nextx,nexty,nextcost });
					}
				}
			}
		}
	}
	cout << ans << endl;

	return 0;
}
accuracy: 1
time_ms: 700
memory_kb: 71140
final_rank: 16

code_snippet: #include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <algorithm>
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <functional>
#include <iostream>
#define MOD 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int n,m,k;
int x[100001],y[100001];
map<ll,int> g;
int cost[100001];

int bfs(){
	queue<int> que;
	queue<int> que2;
	bool flag=false;
	memset(cost,-1,sizeof(cost));
	for(int i=1;i<=m-1;i++){
		ll val=(ll)i*n;
		if(g.find(val)!=g.end()){
			que.push(g[val]);
			cost[g[val]]=0;
		}
	}
	while(que.size()){
		int q=que.front();
		que.pop();
		for(int i=-2;i<=2;i++){
			for(int j=-2;j<=2;j++){
				int nc=0;
				if(abs(i)>1 || abs(j)>1)nc=1;
				int nx=j+x[q],ny=i+y[q];
				if(nx<0)continue;
				if(nx==0 && ny==0)continue;
				if(nx==n-1 && ny==m-1)continue;
				if(ny<0 || nx>=n){
					if(nc==0)return 0;
					if(nc==1)flag=true;
				}
				if(nx>=0 && nx<n && ny>=0 && ny<m){
					ll nval=(ll)ny*n+nx;
					if(g.find(nval)!=g.end()){
						if(cost[g[nval]]==-1){
							cost[g[nval]]=nc;
							if(nc==0)que.push(g[nval]);
							if(nc==1)que2.push(g[nval]);
						}else if(cost[g[nval]]==1 && nc==0){
							cost[g[nval]]=0;
							que.push(g[nval]);
						}
					}
				}
			}
		}
	}
	if(flag)return 1;
	while(que2.size()){
		int q=que2.front();
		que2.pop();
		for(int i=-1;i<=1;i++){
			for(int j=-1;j<=1;j++){
				int nc=0;
				int nx=j+x[q],ny=i+y[q];
				if(nx<0)continue;
				if(nx==0 && ny==0)continue;
				if(nx==n-1 && ny==m-1)continue;
				if(ny<0 || nx>=n)return 1;
				if(nx>=0 && nx<n && ny>=0 && ny<m){
					ll nval=(ll)ny*n+nx;
					if(g.find(nval)!=g.end()){
						if(cost[g[nval]]==-1){
							cost[g[nval]]=1;
							que2.push(g[nval]);
						}
					}
				}
			}
		}
	}
	return 2;
}

int bfs2(){
	queue<int> que;
	queue<int> que2;
	bool flag=false;
	memset(cost,-1,sizeof(cost));
	for(int i=1;i<=n-1;i++){
		ll val=i;
		if(g.find(val)!=g.end()){
			que.push(g[val]);
			cost[g[val]]=0;
		}
	}
	while(que.size()){
		int q=que.front();
		que.pop();
		for(int i=-2;i<=2;i++){
			for(int j=-2;j<=2;j++){
				int nc=0;
				if(abs(i)>1 || abs(j)>1)nc=1;
				int nx=j+x[q],ny=i+y[q];
				if(ny<0)continue;
				if(nx==0 && ny==0)continue;
				if(nx==n-1 && ny==m-1)continue;
				if(nx<0 || ny>=m){
					if(nc==0)return 0;
					if(nc==1)flag=true;
				}
				if(nx>=0 && nx<n && ny>=0 && ny<m){
					ll nval=(ll)ny*n+nx;
					if(g.find(nval)!=g.end()){
						if(cost[g[nval]]==-1){
							cost[g[nval]]=nc;
							if(nc==0)que.push(g[nval]);
							if(nc==1)que2.push(g[nval]);
						}else if(cost[g[nval]]==1 && nc==0){
							cost[g[nval]]=0;
							que.push(g[nval]);
						}
					}
				}
			}
		}
	}
	if(flag)return 1;
	while(que2.size()){
		int q=que2.front();
		que2.pop();
		for(int i=-1;i<=1;i++){
			for(int j=-1;j<=1;j++){
				int nc=0;
				int nx=j+x[q],ny=i+y[q];
				if(ny<0)continue;
				if(nx==0 && ny==0)continue;
				if(nx==n-1 && ny==m-1)continue;
				if(nx<0 || ny>=m)return 1;
				if(nx>=0 && nx<n && ny>=0 && ny<m){
					ll nval=(ll)ny*n+nx;
					if(g.find(nval)!=g.end()){
						if(cost[g[nval]]==-1){
							cost[g[nval]]=1;
							que2.push(g[nval]);
						}
					}
				}
			}
		}
	}
	return 2;
}

int bfs3(){
	queue<int> que;
	queue<int> que2;
	bool flag=false;
	memset(cost,-1,sizeof(cost));
	for(int i=0;i<=n-2;i++){
		ll val=(ll)n*(m-1)+i;
		if(g.find(val)!=g.end()){
			que.push(g[val]);
			cost[g[val]]=0;
		}
	}
	while(que.size()){
		int q=que.front();
		que.pop();
		for(int i=-2;i<=2;i++){
			for(int j=-2;j<=2;j++){
				int nc=0;
				if(abs(i)>1 || abs(j)>1)nc=1;
				int nx=j+x[q],ny=i+y[q];
				if(ny>=m)continue;
				if(nx==0 && ny==0)continue;
				if(nx==n-1 && ny==m-1)continue;
				if(nx>=n || ny<0){
					if(nc==0)return 0;
					if(nc==1)flag=true;
				}
				if(nx>=0 && nx<n && ny>=0 && ny<m){
					ll nval=(ll)ny*n+nx;
					if(g.find(nval)!=g.end()){
						if(cost[g[nval]]==-1){
							cost[g[nval]]=nc;
							if(nc==0)que.push(g[nval]);
							if(nc==1)que2.push(g[nval]);
						}else if(cost[g[nval]]==1 && nc==0){
							cost[g[nval]]=0;
							que.push(g[nval]);
						}
					}
				}
			}
		}
	}
	if(flag)return 1;
	while(que2.size()){
		int q=que2.front();
		que2.pop();

		for(int i=-1;i<=1;i++){
			for(int j=-1;j<=1;j++){
				int nc=0;
				int nx=j+x[q],ny=i+y[q];
				if(ny>=m)continue;
				if(nx==0 && ny==0)continue;
				if(nx==n-1 && ny==m-1)continue;
				if(nx>=n || ny<0)return 1;
				if(nx>=0 && nx<n && ny>=0 && ny<m){
					ll nval=(ll)ny*n+nx;
					if(g.find(nval)!=g.end()){
						if(cost[g[nval]]==-1){
							cost[g[nval]]=1;
							que2.push(g[nval]);
						}
					}
				}
			}
		}
	}
	return 2;
}


int bfs4(){
	queue<int> que;
	queue<int> que2;
	bool flag=false;
	memset(cost,-1,sizeof(cost));
	for(int i=0;i<=m-2;i++){
		ll val=(ll)i*n+n-1;
		if(g.find(val)!=g.end()){
			que.push(g[val]);
			cost[g[val]]=0;
		}
	}
	while(que.size()){
		int q=que.front();
		que.pop();
		for(int i=-2;i<=2;i++){
			for(int j=-2;j<=2;j++){
				int nc=0;
				if(abs(i)>1 || abs(j)>1)nc=1;
				int nx=j+x[q],ny=i+y[q];
				if(nx>=n)continue;
				if(nx==0 && ny==0)continue;
				if(nx==n-1 && ny==m-1)continue;
				if(ny>=m || nx<0){
					if(nc==0)return 0;
					if(nc==1)flag=true;
				}
				if(nx>=0 && nx<n && ny>=0 && ny<m){
					ll nval=(ll)ny*n+nx;
					if(g.find(nval)!=g.end()){
						if(cost[g[nval]]==-1){
							cost[g[nval]]=nc;
							if(nc==0)que.push(g[nval]);
							if(nc==1)que2.push(g[nval]);
						}else if(cost[g[nval]]==1 && nc==0){
							cost[g[nval]]=0;
							que.push(g[nval]);
						}
					}
				}
			}
		}
	}
	if(flag)return 1;
	while(que2.size()){
		int q=que2.front();
		que2.pop();
		for(int i=-1;i<=1;i++){
			for(int j=-1;j<=1;j++){
				int nc=0;
				int nx=j+x[q],ny=i+y[q];
				if(nx>=n)continue;
				if(nx==0 && ny==0)continue;
				if(nx==n-1 && ny==m-1)continue;
				if(ny>=m || nx<0)return 1;
				if(nx>=0 && nx<n && ny>=0 && ny<m){
					ll nval=(ll)ny*n+nx;
					if(g.find(nval)!=g.end()){
						if(cost[g[nval]]==-1){
							cost[g[nval]]=1;
							que2.push(g[nval]);
						}
					}
				}
			}
		}
	}
	return 2;
}


int main(void){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=0;i<k;i++){
		scanf("%d%d",&x[i],&y[i]);
		g[(ll)y[i]*n+x[i]]=i;
	}
	int res=2;
	res=min(res,bfs());
	res=min(res,bfs2());
	res=min(res,bfs3());
	res=min(res,bfs4());
	printf("%d\n",res);
	return 0;
}
accuracy: 1
time_ms: 1220
memory_kb: 10804
final_rank: 11

code_snippet: #include<bits/stdc++.h>
 
using namespace std;
 
struct UnionFind
{
  vector< int > data;
 
  UnionFind(int sz)
  {
    data.assign(sz, -1);
  }
 
  bool unite(int x, int y)
  {
    x = find(x), y = find(y);
    if(x == y) return (false);
    if(data[x] > data[y]) swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }
 
  int find(int k)
  {
    if(data[k] < 0) return (k);
    return (data[k] = find(data[k]));
  }
 
  int size(int k)
  {
    return (-data[find(k)]);
  }
};
 
int main()
{
  int N, M, K, X[100000], Y[100000];
 
  cin >> N >> M >> K;
 
  map< pair< int, int >, int > vs;
  for(int i = 0; i < K; i++) {
    cin >> X[i] >> Y[i];
    vs[{X[i], Y[i]}] = i;
  }
 
  UnionFind tree(K);
  for(int i = 0; i < K; i++) {
    for(int j = -1; j <= 1; j++) {
      for(int k = -1; k <= 1; k++) {
        int x = X[i] + j, y = Y[i] + k;
        if(vs.count({x, y})) tree.unite(vs[{x, y}], i);
      }
    }
  }
 
 
  set< int > link1, link2;
  for(int i = 0; i < K; i++) {
    if(X[i] == 0 || Y[i] == M - 1) link1.emplace(tree.find(i));
    if(X[i] == N - 1 || Y[i] == 0) link2.emplace(tree.find(i));
  }
 
  for(auto &v : link1) {
    if(link2.count(v)) {
      cout << 0 << endl;
      return (0);
    }
  }
 
  for(int i = 0; i < K; i++) {
    for(int j = -1; j <= 1; j++) {
      for(int k = -1; k <= 1; k++) {
        int x = X[i] + j, y = Y[i] + k;
        if(x < 0 || y < 0 || x >= N || y >= M) continue;
        if(x == 0 && y == 0) continue;
        if(x == N - 1 && y == M - 1) continue;
        if(vs.count({x, y})) continue;
 
        bool up = false, down = false;
        up |= link1.count(tree.find(vs[{X[i], Y[i]}]));
        down |= link2.count(tree.find(vs[{X[i], Y[i]}]));
 
        if(x == 0 || y == M - 1) up = true;
        if(x == N - 1 || y == 0) down = true;
 
        for(int l = -1; l <= 1; l++) {
          for(int m = -1; m <= 1; m++) {
            int xx = x + l, yy = y + m;
            if(xx < 0 || yy < 0 || xx >= N || yy >= M) continue;
            if(!vs.count({xx, yy})) continue;
            up |= link1.count(tree.find(vs[{xx, yy}]));
            down |= link2.count(tree.find(vs[{xx, yy}]));
          }
        }
 
        if(up && down) {
          cout << 1 << endl;
          return (0);
        }
      }
    }
  }
 
 
  cout << 2 << endl;
}
accuracy: 1
time_ms: 860
memory_kb: 10232
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
#define MAX_K 100005
int N,M,K;
P t[MAX_K];
map<P,bool> mp;

int main(){
  scanf("%d %d %d",&N,&M,&K);
  for(int i=0;i<K;i++){
    int x,y;
    scanf("%d %d",&y,&x);
    y++;
    x++;
    mp[P(y,x)]=1;
  }
  
  for(int y=3;y<=N+1;y++)mp[P(y,0)]=1;
  for(int y=0;y<=N-2;y++)mp[P(y,M+1)]=1;
  for(int x=3;x<=M+1;x++)mp[P(0,x)]=1;
  for(int x=0;x<=M-2;x++)mp[P(N+1,x)]=1;

  bool ans=false;
  queue< P > Q;
  map< P , int > visited;
  visited[ P(N+1,0) ]=1;
  Q.push( P(N+1,0) );
  visited[ P(0,M+1) ]=2;
  Q.push( P(0,M+1) );
  
  while(!Q.empty()){
    P p=Q.front();Q.pop();

    for(int dy=-2;dy<=2;dy++){
      for(int dx=-2;dx<=2;dx++){
        P np=p;
        np.first+=dy;
        np.second+=dx;
        if( visited.count(np)==0 )continue;
        if(visited[np]!=visited[p])ans=true;
      }
    }
    for(int dy=-1;dy<=1;dy++){
      for(int dx=-1;dx<=1;dx++){
        P np=p;
        np.first+=dy;
        np.second+=dx;
        if(visited.count(np)){
          if(visited[np]!=visited[p]){
            printf("0\n");
            return 0;
          }
          continue;
        }
        if(mp.count(np)==0)continue;
        visited[np]=visited[p];
        Q.push(np);
      }
    }
  }
  if(ans)printf("1\n");
  else printf("2\n");
  return 0;
}
accuracy: 1
time_ms: 1720
memory_kb: 66496
final_rank: 18

code_snippet: #include <cstdio>
#include <vector>
#include <map>

class Union_Find {
  public:
    std::vector<int> par, rank;
    
    Union_Find(int N) {
        par.resize(N); rank.resize(N);

        for (int i = 0; i < N; i++) {
            par[i] = i;
            rank[i] = 0;
        }
    }

    int find(int x)
    {
        if (par[x] == x) {
            return x;
        }
        return par[x] = find(par[x]);
    }

    void unite(int x, int y)
    {
        x = find(x);
        y = find(y);
        if (x == y) return;
        
        if (rank[x] < rank[y]) {
            par[x] = y;
        } else {
            par[y] = x;
            if (rank[x] == rank[y]) {
                rank[x]++;
            }
        }
    }

    bool same(int x, int y)
    {
        return find(x) == find(y);
    }
};

bool in_field(int x, int y, int N, int M)
{
    return 0 <= x && x < N && 0 <= y && y < M;
}

bool is_connect(int x, int y, int N, int M)
{
    if (x == 0 && y == 0) return 0; // start
    if (x == N - 1 && y == M - 1) return 0; // goal    
    return 1;
}

bool check(int x, int y, int N, int M)
{    
    return is_connect(x, y, N, M) && in_field(x, y, N, M);
}

int main()
{    
    std::map<std::pair<int, int>, int> f;
    
    int N, M, K;
    scanf("%d %d %d", &N, &M, &K);
    std::vector<int> x(K), y(K);
    
    for (int i = 0; i < K; i++) {
        scanf("%d %d", &x[i], &y[i]);
        f[{y[i], x[i]}] = i;        
    }
    
    constexpr int dx[] = {-1, -1, -1, +0, +0, +1, +1, +1};
    constexpr int dy[] = {-1, +0, +1, -1, +1, -1, +0, +1};
    
    Union_Find uf(K + 4);    
    int res = 2;
    for (int i = 0; i < K; i++) {
        for (int j = 0; j < 8; j++) {
            int nx = x[i] + dx[j], ny = y[i] + dy[j];
            if (check(nx, ny, N, M)) {
                if (f.count({ny, nx})) {
                    uf.unite(i, f[{ny, nx}]);
                }
            } else {
                if (nx == -1) uf.unite(i, K);     // left
                if (ny == -1) uf.unite(i, K + 1); // up
                if (nx == N)  uf.unite(i, K + 2); // right
                if (ny == M)  uf.unite(i, K + 3); // down
            }
        }
        
        if (uf.same(K, K + 1) ||      // connect left & up
            uf.same(K, K + 2) ||      // connect left & right
            uf.same(K + 1, K + 3) ||  // connect up & down
            uf.same(K + 2, K + 3)) {  // connect right & down
            res = 0;
        }        
    }   
    
    for (int i = 0; i < K; i++) {
        for (int j = 0; j < 8; j++) {
            int nx = x[i] + dx[j], ny = y[i] + dy[j];
            if (!check(nx, ny, N, M) || f.count({ny, nx})) {
                continue;
            }
            std::vector<bool> fill(4);
            for (int k = 0; k < 8; k++) {
                int nnx = nx + dx[k], nny = ny + dy[k];
                if (!is_connect(nnx, nny, N, M)) continue;
                if (nnx == -1) fill[0] = 1; // left               
                if (nny == -1) fill[1] = 1; // up
                if (nnx == N)  fill[2] = 1; // right
                if (nny == M)  fill[3] = 1; // down

                if (f.count({nny, nnx})) {
                    int p = f[{nny, nnx}];                                    
                    if (uf.same(p, K))     fill[0] = 1; // left
                    if (uf.same(p, K + 1)) fill[1] = 1; // up
                    if (uf.same(p, K + 2)) fill[2] = 1; // right
                    if (uf.same(p, K + 3)) fill[3] = 1; // down
                }
            }

            if ((fill[0] && fill[1]) || // connect left & up
                (fill[0] && fill[2]) || // connect left & right
                (fill[1] && fill[3]) || // connect up & down
                (fill[2] && fill[3])) { // connect right & down
                res = std::min(res, 1);
            }
        }
    }
    printf("%d\n", res);
    return 0;
}
accuracy: 1
time_ms: 620
memory_kb: 10452
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define MAX 1000000
vector<int> G[MAX];
int ord[MAX], low[MAX];
bool ans[MAX];
bool visited[MAX];

void dfs(int pos){
  if(ans[pos])return;
  if(visited[pos])return;
  visited[pos]=true;
  for(int i=0;i<(int)G[pos].size();i++){
    dfs(G[pos][i]);
  }
}

void rec(int pos,int prev,int& k){
  low[pos]=ord[pos]=k++;
  int flg=0,child=0;
  for(int i=0;i<(int)G[pos].size();i++){
    int to=G[pos][i];
    if(to==prev)continue;
    if(ord[to]==-1){
      child++;
      rec(to,pos,k);
      low[pos]=min(low[pos],low[to]);
      if(low[to]>=ord[pos]&&prev!=-1)flg=true;
    }
    low[pos]=min(low[pos],ord[to]);
  }
  if(prev==-1&&child>=2)flg=true;
  if(flg)ans[pos]=true;
}


int W,H,K;
map<int,int> mp;
map<int,int> t;

int main(){
  scanf("%d %d %d",&W,&H,&K);
  for(int i=0;i<K;i++){
    int x,y;
    scanf("%d %d",&x,&y);
    mp[ W*y+x ]=1;
  }
  map<int,int> :: iterator it;

  int cc=0;
  for(int y=0;y<H;y++){
    int x=0;
    if(mp.count(y*W+x)==0&&t.count(y*W+x)==0)t[y*W+x]=cc++;
    x=W-1;
    if(mp.count(y*W+x)==0&&t.count(y*W+x)==0)t[y*W+x]=cc++;
  }
  
  for(int x=0;x<W;x++){
    int y=0;
    if(mp.count(y*W+x)==0&&t.count(y*W+x)==0)t[y*W+x]=cc++;
    y=H-1;
    if(mp.count(y*W+x)==0&&t.count(y*W+x)==0)t[y*W+x]=cc++;
  }
  for(it=mp.begin();it!=mp.end();it++){
    int x=it->first%W;
    int y=it->first/W;
    for(int i=-1;i<=1;i++){
      for(int j=-1;j<=1;j++){
        if(abs(i)==abs(j))continue;
        
        int nx=x+i;
        int ny=y+j;
        if(nx<0||ny<0||nx>=W||ny>=H)continue;
        if(mp.count( ny*W+nx ))continue;
        t[ny*W+nx]=cc++;        
      }
    }
  }




  for(it=t.begin();it!=t.end();it++){

    int x=it->first%W;
    int y=it->first/W;
    
    for(int dy=-1;dy<=1;dy++){
      for(int dx=-1;dx<=1;dx++){
        if(dy==dx)continue;
        int ny=y+dy;
        int nx=x+dx;
        if(t.count(ny*W+nx)){
          int from=it->second, to=t[ny*W+nx];
          G[from].push_back(to);
          G[to].push_back(from);
        }
      }
    }
    
  }

  for(int i=0;i<MAX;i++)low[i]=1e8, ord[i]=-1;
  int tmp=0;
  rec(0,-1,tmp);

  dfs(0);

  if(visited[ t[ (H-1)*W+W-1 ] ])printf("2\n");
  else printf("1\n");
  
  
  return 0;
}
accuracy: 0.05263157894736842
time_ms: 10
memory_kb: 34396
final_rank: 20

code_snippet: #include<iostream>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define P pair<int,int>
#define mk make_pair
int dx[]={1,1,1,0,0,-1,-1,-1};
int dy[]={1,0,-1,1,-1,1,0,-1};
int ddx[]={-2,-2,-2,-2,-2,-1,-1,0,0,1,1,2,2,2,2,2};
int ddy[]={-2,-1,0,1,2,-2,2,-2,2,-2,2,-2,-1,0,1,2};
int c[4];
int main(){
    map<P,int>s;
    vector<P>v1,v2;
    int n,w,h;
    cin>>w>>h>>n;
    for(int i=0;i<n;i++){
        int x,y;
        cin>>x>>y;
        if(x==0||y==h-1)v1.push_back(mk(x,y));
        if(y==0||x==w-1)v2.push_back(mk(x,y));
        s[mk(x,y)]=0;
    }
    if(s.find(mk(w-1,h-2))!=s.end())c[3]=1;
    if(s.find(mk(w-2,h-1))!=s.end())c[2]=1;
    if(s.find(mk(0,1))!=s.end())c[1]=1;
    if(s.find(mk(1,0))!=s.end())c[0]=1;
    if((c[0]&&c[1])||(c[2]&&c[3]))goto L0;
    for(vector<P>::iterator it=v1.begin();it!=v1.end();it++){
        int x=(*it).first,y=(*it).second;
        if(s[mk(x,y)]==0){
            queue<P>q;
            q.push(mk(x,y));
	    if(y==0||x==w-1)goto L0;
            s[mk(x,y)]=1;
            while(!q.empty()){
                P po=q.front();q.pop();
                int xx=po.first,yy=po.second;
                for(int i=0;i<8;i++){
                    int px=xx+dx[i],py=yy+dy[i];
                    if(s.find(mk(px,py))!=s.end())if(s[mk(px,py)]==0){
                        if(py==0||px==w-1)goto L0;
                        s[mk(px,py)]=1;
                        q.push(mk(px,py));
                    }
                }
            }
        }
    }
    for(vector<P>::iterator it=v2.begin();it!=v2.end();it++){
        int x=(*it).first,y=(*it).second;
        if(s[mk(x,y)]==0){
            queue<P>q;
            q.push(mk(x,y));
	    if(x==0||y==h-1)goto L0;
            s[mk(x,y)]=2;
            while(!q.empty()){
                P po=q.front();q.pop();
                int xx=po.first,yy=po.second;
                for(int i=0;i<16;i++){
                    int px=xx+ddx[i],py=yy+ddy[i];
                    if(s.find(mk(px,py))!=s.end()){
                        if(s[mk(px,py)]==1)goto L1;
                    }
                }
                for(int i=0;i<8;i++){
                    int px=xx+dx[i],py=yy+dy[i];
                    if(s.find(mk(px,py))!=s.end())if(s[mk(px,py)]==0){
                        if(px==0||py==h-1)goto L0;
                        s[mk(px,py)]=2;
                        q.push(mk(px,py));
                    }
                }
            }
        }
    }
    for(int i=0;i<4;i++)if(c[i])goto L1;
    for(int i=0;i<w;i++)
      for(int j=0;j<8;j++){
	int x=i+dx[j],y=dy[j];
	if(s.find(mk(x,y))!=s.end())
	  if(s[mk(x,y)]==1)goto L1;
	  }
 for(int i=0;i<h;i++)
      for(int j=0;j<8;j++){
	int x=w-1+dx[j],y=i+dy[j];
	if(s.find(mk(x,y))!=s.end())
	  if(s[mk(x,y)]==1)goto L1;
	  }
 for(int i=0;i<w;i++)
      for(int j=0;j<8;j++){
	int x=i+dx[j],y=h-1+dy[j];
	if(s.find(mk(x,y))!=s.end())
	  if(s[mk(x,y)]==2)goto L1;
	  }
 for(int i=0;i<h;i++)
      for(int j=0;j<8;j++){
	int x=0+dx[j],y=i+dy[j];
	if(s.find(mk(x,y))!=s.end())
	  if(s[mk(x,y)]==2)goto L1;
	  }
    goto L2;
    if(0)L0:cout<<0<<endl;
    if(0)L1:cout<<1<<endl;
    if(0)L2:cout<<2<<endl;
}
accuracy: 1
time_ms: 500
memory_kb: 9372
final_rank: 5