#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 100000;
const int MAX_M = 200000;
const int INF = 1 << 30;
const int dxs[] = {1, 0, -1, 0}, dys[] = {0, 1, 0, -1};
template <typename T>
struct Pt {
  T x, y;
  Pt() {}
  Pt(T _x, T _y) : x(_x), y(_y) {}
  Pt(const Pt<T> &p) : x(p.x), y(p.y) {}
  Pt<T> operator+(const Pt<T> p) const { return Pt<T>(x + p.x, y + p.y); }
  Pt<T> operator-() const { return Pt<T>(-x, -y); }
  Pt<T> operator-(const Pt<T> p) const { return Pt<T>(x - p.x, y - p.y); }
  Pt<T> operator*(T t) const { return Pt<T>(x * t, y * t); }
  Pt<T> operator/(T t) const { return Pt<T>(x / t, y / t); }
  T dot(Pt<T> v) const { return x * v.x + y * v.y; }
  T cross(Pt<T> v) const { return x * v.y - y * v.x; }
  Pt<T> mid(const Pt<T> p) { return Pt<T>((x + p.x) / 2, (y + p.y) / 2); }
  T d2() { return x * x + y * y; }
  double d() { return sqrt(d2()); }
  Pt<T> rot(double th) {
    double c = cos(th), s = sin(th);
    return Pt<T>(c * x - s * y, s * x + c * y);
  }
  bool operator==(const Pt<T> pt) const { return x == pt.x && y == pt.y; }
  bool operator<(const Pt<T> &pt) const {
    return x < pt.x || (x == pt.x && y < pt.y);
  }
  void print() { printf("(%d,%d)", x, y); }
};
int lxs[MAX_N], rxs[MAX_N];
Pt<int> sps[MAX_M], ps[MAX_M];
void convex_hull(int n, Pt<int> ps[], vector<Pt<int> > &chs) {
  vector<Pt<int> > lhs, uhs;
  lhs.push_back(ps[0]);
  lhs.push_back(ps[1]);
  for (int i = 2; i < n; i++) {
    while (lhs.size() >= 2) {
      int ln = lhs.size();
      Pt<int> &lh0 = lhs[ln - 2], &lh1 = lhs[ln - 1];
      if ((lh1 - lh0).cross(ps[i] - lh1) > 0) break;
      lhs.pop_back();
    }
    lhs.push_back(ps[i]);
  }
  uhs.push_back(ps[n - 1]);
  uhs.push_back(ps[n - 2]);
  for (int i = n - 3; i >= 0; i--) {
    while (uhs.size() >= 2) {
      int un = uhs.size();
      Pt<int> &uh0 = uhs[un - 2], &uh1 = uhs[un - 1];
      if ((uh1 - uh0).cross(ps[i] - uh1) > 0) break;
      uhs.pop_back();
    }
    uhs.push_back(ps[i]);
  }
  lhs.pop_back();
  uhs.pop_back();
  chs.clear();
  chs.reserve(lhs.size() + uhs.size());
  chs.assign(lhs.begin(), lhs.end());
  chs.insert(chs.end(), uhs.begin(), uhs.end());
}
inline void setmin(int &a, int b) {
  if (a > b) a = b;
}
inline void setmax(int &a, int b) {
  if (a < b) a = b;
}
inline bool iszero(int n, int x, int y) {
  return (x < 0 || x >= n || y < 0 || y >= n || x < lxs[y] || x > rxs[y]);
}
int main() {
  for (int n, m; scanf("%d%d", &n, &m) == 2 && n > 0;) {
    fill(lxs, lxs + n, INF);
    fill(rxs, rxs + n, -1);
    for (int i = 0; i < m; i++) {
      scanf("%d%d", &sps[i].x, &sps[i].y);
      sps[i].x--, sps[i].y--;
      setmin(lxs[sps[i].y], sps[i].x);
      setmax(rxs[sps[i].y], sps[i].x);
    }
    sort(sps, sps + m);
    int l = 0;
    for (int i = 0; i < m; i++) {
      int x = sps[i].x, y = sps[i].y;
      int c = 0, b = 0;
      for (int di = 0; di < 4; di++) {
        int vx = x + dxs[di], vy = y + dys[di];
        if (!iszero(n, vx, vy)) c++, b |= (1 << di);
      }
      if (c == 2) {
        switch (b) {
          case 3:
            ps[l] = Pt<int>(x + 1, y + 1);
            break;
          case 6:
            ps[l] = Pt<int>(x, y + 1);
            break;
          case 12:
            ps[l] = Pt<int>(x, y);
            break;
          case 9:
            ps[l] = Pt<int>(x + 1, y);
            break;
        }
        l++;
      }
    }
    sort(ps, ps + l);
    l = unique(ps, ps + l) - ps;
    vector<Pt<int> > cps;
    convex_hull(l, ps, cps);
    int k = cps.size();
    printf("%d\n", k);
    for (int i = 0, j = 0; i < k; i++, j = (j + k - 1) % k)
      printf("%d %d\n", cps[j].x, cps[j].y);
  }
  return 0;
}
