#include <iostream>
#include <climits>
#include <queue>
#include <cmath>
#include <stack>
using namespace std;

struct vec
{
	long int tail;
	long int dx;
	long int dy;
	//float angle;
	float length;
	vec(int a, int b, int c, float d)
	{
		tail = a;
		dx = b;
		dy = c;
		length = d;
	}
};

struct POL //Point on line
{
	long int num;
	float dis;
	POL(int n, float d)
	{
		num = n;
		dis = d;
	}
};

float cal_angle(float dx, float dy)
{
	float angle;
	float dis = sqrt(dx * dx + dy * dy);
	angle = acos(dx / dis);
	return angle;
}

float cal_dis(float dx, float dy)
{
	return sqrt(dx * dx + dy * dy);
}

bool on_left(int x1, int y1, int x2, int y2)
{
	if ((x1 * y2 - y1 * x2) >= 0)
	{
		return true;
	}
	else
		return false;
}

bool operator < (const vec& a, const vec& b)
{
	if ((a.dx * b.dy - a.dy * b.dx) > 0)  //a is under b
		return false;
	if ((a.dx * b.dy - a.dy * b.dx) < 0) // a is upon b
		return true;
	if ((a.dx * b.dy - a.dy * b.dx) == 0)
	{
		if (a.dx == b.dx && a.dx == 0)
		{
			return a.dy < b.dy;
		}
		else
			return a.dx > b.dx;
	}
		
}


bool operator < (const POL& a, const POL& b)
{
		return a.dis < b.dis;
}



int main()
{
	
	long int v;
	cin >> v;
	long int* v_x = new long int[v];
	long int* v_y = new long int[v];
	long int min_x = LONG_MAX;
	long int min_y = LONG_MAX;
	long int start;
	for (int i = 0; i < v; i++)
	{
		long int x, y;
		cin >> x >> y;
		v_x[i] = x;
		v_y[i] = y;
		if (y == min_y)
		{
			if (x < min_x)
			{
				min_x = x;
				start = i;
			}
			continue;
		}
		if (y < min_y)
		{
			min_x = x;
			min_y = y;
			start = i;
		}
	}
	priority_queue<vec> q;
	for (int i = 0; i < v; i++)
	{
		if (i == start)
			continue;
		float dx = v_x[i] - v_x[start];
		float dy = v_y[i] - v_y[start];
		//float angle = cal_angle(dx, dy);
		float length = cal_dis(dx, dy);
		vec VCT(i,dx,dy,length);
		q.push(VCT);
	}

	stack<int> s;
	s.push(start);
	vec new_out = q.top();
	q.pop();
	s.push(new_out.tail);
	while (!q.empty())
	{
		new_out = q.top();
		q.pop();
		while (1)
		{
			int top = s.top();
			s.pop();
			int pre = s.top();
			s.push(top);
			int px = v_x[top] - v_x[pre];
			int py = v_y[top] - v_y[pre];
			int nx = v_x[new_out.tail] - v_x[top];
			int ny = v_y[new_out.tail] - v_y[top];
			if (on_left(px, py, nx, ny))
			{
				s.push(new_out.tail);
				break;
			}
			else
			{
				s.pop();
			}
		}
	}
	priority_queue<POL> q1;
	int swt = 0;
	while (1)
	{
		int n_top = s.top();
		s.pop();
		int n_pre = s.top();
		s.push(n_top);
		int dx1 = v_x[n_top] - v_x[start];
		int dy1 = v_y[n_top] - v_y[start];
		int dx2 = v_x[n_pre] - v_x[start];
		int dy2 = v_y[n_pre] - v_y[start];
		//float t = cal_angle(dx1, dy1) - cal_angle(dx2, dy2);
		if (dy1 == dy2 && dy2 == 0)
		{
			swt = 1;
			break;
		}
		if ((dx1 * dy2 - dx2 * dy1) == 0)
		{
			s.pop();
		}
		else
		{
			break;
		}
	}

	int end = s.top();
	float e_dx = v_x[end] - v_x[start];
	float e_dy = v_y[end] - v_y[start];
	for (int i = 0; i < v; i++)
	{
		if (swt)
			break;
		if (v_x[i] == v_x[end] && v_y[i] == v_y[end])
			continue;
		if (v_x[i] == v_x[start] && v_y[i] == v_y[start])
			continue;
		float dx = v_x[i] - v_x[start];
		float dy = v_y[i] - v_y[start];
		//float e_angle1 = cal_angle(v_x[i] - v_x[start], v_y[i] - v_y[start]);
		if ((e_dx * dy - e_dy * dx) == 0)
		{
			float length = cal_dis(dx, dy);
			POL p(i, length);
			q1.push(p);
		}
	}
	while (!q1.empty())
	{
		int n_p = q1.top().num;
		s.push(n_p);
		q1.pop();
	}

	long int sz = s.size();
	long int* result = new long int[sz];
	for (int i = sz - 1; i >= 0; i--)
	{
		int rn = s.top();
		s.pop();
		result[i] = rn;
	}
	cout << sz << endl;
	for (int i = 0; i < sz; i++)
		cout << v_x[result[i]] <<" "<< v_y[result[i]] << endl;
	return 0;


}



Measured memory_bytes: 8516