Problem: Problem

The great devil Sacagna was still attacked by her natural enemy cat today.
I bought a secret weapon because I couldn't do it all the time.
This secret weapon can block the cat's path of movement by creating huge rocks that keep cats away from you.


Now, Sacagna and one cat are in a rectangular closed section surrounded by trout (0,0), (n−1,0), (n−1, m−1), (0, m−1). I'm in.
There is a cat in the trout (0,0) and Sacagna in the trout (n−1, m−1).
Cats can move to adjacent squares on the top, bottom, left, and right, but cannot go out of the section.
Some squares cannot enter due to the effects of holes and obstacles.
Sacagna can prevent cats from invading a square by creating a rock in that square.
However, rocks cannot be formed on the trout (0,0) and the trout (n−1, m−1).

Find the minimum number of rocks to form needed to block the path of movement from trout (0,0) to trout (n−1, m−1).

Constraints

The input satisfies the following conditions.

* 2 ≤ n, m ≤ 105
* 0 ≤ k ≤ min (n × m−2,105)
* 0 ≤ xi ≤ n − 1
* 0 ≤ yi ≤ m − 1
* (xi, yi) ≠ (xj, yj) (i ≠ j)
* (xi, yi) ≠ (0,0) ≠ (n−1, m−1)

Input


n m k
x1 y1
...
xk yk


All inputs are given as integers.
On the first line, two integers n and m representing the size of the squares and the number k of the squares that cannot be penetrated are given separated by blanks.
From the second line, the coordinates of the cells that cannot enter the k line are given.

Output

Output the minimum number of rocks to be generated in one line, which is necessary to block the movement path from the mass (0,0) to the mass (n−1, m−1).

Examples

Input

3 5 2
0 2
2 2


Output

1


Input

5 5 3
0 2
2 2
4 1


Output

2

Solution (in CPP):

Solution:
// need
#include <iostream>
#include <algorithm>

// data structure
#include <bitset>
//#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
//#include <array>
//#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <complex>
//#include <deque>
#include<valarray>

// stream
//#include <istream>
//#include <sstream>
//#include <ostream>

// etc
#include <cassert>
#include <functional>
#include <iomanip>
//#include <typeinfo>
#include <chrono>
#include <random>
#include <numeric>

#define INIT std::ios::sync_with_stdio(false);std::cin.tie(0);
#define VAR(type, ...)type __VA_ARGS__;MACRO_VAR_Scan(__VA_ARGS__);
template<typename T> void MACRO_VAR_Scan(T& t) { std::cin >> t; }
template<typename First, typename...Rest>void MACRO_VAR_Scan(First& first, Rest&...rest) { std::cin >> first; MACRO_VAR_Scan(rest...); }
#define VEC_ROW(type, n, ...)std::vector<type> __VA_ARGS__;MACRO_VEC_ROW_Init(n, __VA_ARGS__); for(int i=0; i<n; ++i){MACRO_VEC_ROW_Scan(i, __VA_ARGS__);}
template<typename T> void MACRO_VEC_ROW_Init(int n, T& t) { t.resize(n); }
template<typename First, typename...Rest>void MACRO_VEC_ROW_Init(int n, First& first, Rest&...rest) { first.resize(n); MACRO_VEC_ROW_Init(n, rest...); }
template<typename T> void MACRO_VEC_ROW_Scan(int p, T& t) { std::cin >> t[p]; }
template<typename First, typename...Rest>void MACRO_VEC_ROW_Scan(int p, First& first, Rest&...rest) { std::cin >> first[p]; MACRO_VEC_ROW_Scan(p, rest...); }
#define OUT(d) std::cout<<d;
#define FOUT(n, d) std::cout<<std::fixed<<std::setprecision(n)<<d;
#define SOUT(n, c, d) std::cout<<std::setw(n)<<std::setfill(c)<<d;
#define SP std::cout<<" ";
#define TAB std::cout<<"\t";
#define BR std::cout<<"\n";
#define ENDL std::cout<<std::endl;
#define FLUSH std::cout<<std::flush;
#define VEC(type, c, n) std::vector<type> c(n);for(auto& i:c)std::cin>>i;
#define MAT(type, c, m, n) std::vector<std::vector<type>> c(m, std::vector<type>(n));for(auto& r:c)for(auto& i:r)std::cin>>i;
#define ALL(a) (a).begin(),(a).end()
#define FOR(i, a, b) for(int i=(a);i<(b);++i)
#define RFOR(i, a, b) for(int i=(b)-1;i>=(a);--i)
#define REP(i, n) for(int i=0;i<int(n);++i)
#define RREP(i, n) for(int i=(n)-1;i>=0;--i)
#define FORLL(i, a, b) for(ll i=ll(a);i<ll(b);++i)
#define RFORLL(i, a, b) for(ll i=ll(b)-1;i>=ll(a);--i)
#define REPLL(i, n) for(ll i=0;i<ll(n);++i)
#define RREPLL(i, n) for(ll i=ll(n)-1;i>=0;--i)
#define PAIR std::pair<int, int>
#define PAIRLL std::pair<ll, ll>
#define IN(a, x, b) (a<=x && x<b)
#define SHOW(d) {std::cerr << #d << "\t:" << d << "\n";}
#define SHOWVECTOR(v) {std::cerr << #v << "\t:";for(const auto& xxx : v){std::cerr << xxx << " ";}std::cerr << "\n";}
#define SHOWVECTOR2(v) {std::cerr << #v << "\t:\n";for(const auto& xxx : v){for(const auto& yyy : xxx){std::cerr << yyy << " ";}std::cerr << "\n";}}
#define SHOWPAIR(p) {std::cerr << #p << "\t:(" << p.first << ",\t" << p.second << ")\n";}
#define SHOWPAIRVECTOR2(v) {std::cerr << #v << "\t:\n";for(const auto& xxx : v){for(const auto& yyy : xxx){std::cerr<<'('<<yyy.first<<", "<<yyy.second<<") ";}std::cerr << "\n";}}
#define SHOWPAIRVECTOR(v) {for(const auto& xxx:v){std::cerr<<'('<<xxx.first<<", "<<xxx.second<<") ";}std::cerr<<"\n";}
#define SHOWQUEUE(a) {std::queue<decltype(a.front())> tmp(a);std::cerr << #a << "\t:";for(int i=0; i<static_cast<int>(a.size()); ++i){std::cerr << tmp.front() << "\n";tmp.pop();}std::cerr << "\n";}
template<typename T> inline T CHMAX(T& a, const T b) { return a = (a < b) ? b : a; }
template<typename T> inline T CHMIN(T& a, const T b) { return a = (a > b) ? b : a; }
#define EXCEPTION(msg) throw std::string("Exception : " msg " [ in ") + __func__ + " : " + std::to_string(__LINE__) + " lines ]"
#define TRY(cond, msg) try {if (cond) EXCEPTION(msg);}catch (std::string s) {std::cerr << s << std::endl;}
void CHECKTIME(std::function<void()> f) { auto start = std::chrono::system_clock::now(); f(); auto end = std::chrono::system_clock::now(); auto res = std::chrono::duration_cast<std::chrono::nanoseconds>((end - start)).count(); std::cerr << "[Time:" << res << "ns  (" << res / (1.0e9) << "s)]\n"; }

#define int ll
using ll = long long;
using ull = unsigned long long;
constexpr int INFINT = 1 << 30;                          // 1.07x10^ 9
constexpr int INFINT_LIM = (1LL << 31) - 1;              // 2.15x10^ 9
constexpr ll INFLL = 1LL << 60;                          // 1.15x10^18
constexpr ll INFLL_LIM = (1LL << 62) - 1 + (1LL << 62);  // 9.22x10^18
constexpr double EPS = 1e-7;
constexpr int MOD = 1000000007;
constexpr double PI = 3.141592653589793238462643383279;

//Union-Find
class UnionFind {
private:
	std::vector<int> parent;
	std::vector<int> height;
	std::vector<int> m_size;

public:
	UnionFind(int size_) : parent(size_), height(size_, 0), m_size(size_, 1) {
		REP(i, size_) {
			parent[i] = i;
		}
	}
	void init(int size_) {
		parent.resize(size_);
		height.resize(size_, 0);
		m_size.resize(size_, 0);
		REP(i, size_) {
			parent[i] = i;
		}
	}
	int find(int x) {
		if (parent[x] == x) {
			return x;
		}
		return parent[x] = find(parent[x]);
	}
	void unite(int x, int y) {
		x = find(x);
		y = find(y);
		if (x == y) return;
		int t = size(x) + size(y);
		m_size[x] = m_size[y] = t;
		if (height[x] < height[y]) parent[x] = y;
		else parent[y] = x;
		if (height[x] == height[y]) ++height[x];
	}
	bool same(int x, int y) {
		return find(x) == find(y);
	}
	int size(int x) {
		if (parent[x] == x) {
			return m_size[x];
		}
		return size(parent[x] = find(parent[x]));
	}
};

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

signed main() {
	INIT;
	VAR(int, n, m, k);
	VEC_ROW(int, k, x, y);
	std::map<PAIR, int> map;
	REP(i, k) {
		map[PAIR(y[i], x[i])] = i;
	}
	UnionFind uf(k + 2);
	REP(i, k) {
		REP(d, 8) {
			int dy = y[i] + dy8[d];
			int dx = x[i] + dx8[d];
			if (!IN(0, dx, n) || !IN(0, dy, m)) {
				if (dy < 0) uf.unite(i, k);
				if (dx < 0) uf.unite(i, k + 1);
				if (dy > m - 1) uf.unite(i, k + 1);
				if (dx > n - 1) uf.unite(i, k);
			}
			else {
				if (map.find(PAIR(dy, dx)) == map.end()) continue;
				uf.unite(i, map[PAIR(dy, dx)]);
			}
		}
	}
	if (uf.same(k, k + 1)) {
		OUT(0)BR;
		return 0;
	}
	///////////////////////////////////
	REP(i, k) {
		if (!uf.same(i, k) && !uf.same(i, k + 1)) continue;
		int join = uf.same(i, k + 1);
		REP(d, 16) {
			int dy = y[i] + dy16[d];
			int dx = x[i] + dx16[d];
			if (!IN(0, dx, n) || !IN(0, dy, m)) {
				if (dy < 0 && join == 1 ||
					dx < 0 && join == 0 ||
					dy > m - 1 && join == 0 ||
					dx > n - 1 && join == 1)
				{
					OUT(1)BR;
					return 0;
				}
			}
			else {
				if (map.find(PAIR(dy, dx)) == map.end()) continue;
				if (uf.same(map[PAIR(dy, dx)], k + !join)) {
					OUT(1)BR;
					return 0;
				}
			}
		}
	}
	OUT(2)BR;
	return 0;
}