/*
  Copyright 2013 Marek "p2004a" Rusinowski
  Graham scan
*/
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

class point {
 public:
  int x, y;
  point(int _x, int _y) : x(_x), y(_y) {}
};

inline int det(const point &p0, const point &p1, const point p2) {
  return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}

inline int d(const point &p1, const point &p2) {
  return (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);
}

class comp {
  point p0;
 public:
  comp(const point &p) : p0(p) {}
  bool operator() (const point &p1, const point &p2) {
    int t = det(p0, p1, p2);
    if (t > 0) return true;
    if (t < 0) return false;
    return d(p0, p1) < d(p0, p2);
  }
};

vector<point> graham(vector<point> points) {
  int idx = 0;
  for (int i = 1; i < (int)points.size(); ++i) {
    if (points[i].y < points[idx].y || (points[i].y == points[idx].y && points[i].x < points[idx].x)) idx = i;
  }
  swap(points.back(), points[idx]);
  vector<point> out;
  out.push_back(points.back());
  points.pop_back();
  comp cmp(out[0]);
  sort(points.begin(), points.end(), cmp);

  for (int i = 0; i < (int) points.size(); ++i) {
    while (out.size() >= 2 && det(out[out.size() - 2], out.back(), points[i]) < 0) {
      out.pop_back();
    }
    out.push_back(points[i]);
  }

  return out;
}

int main() {
  int n;
  scanf("%d", &n);
  vector<point> points;
  for (int i = 0; i < n; ++i) {
    int a, b;
    scanf("%d%d", &a, &b);
    points.push_back(point(a, b));
  }
  vector<point> out = graham(points);

  for (int i = 0; i < (int) out.size(); ++i) {
    printf("%d %d\n", out[i].x, out[i].y);
  }
  return 0;
}
