#include <bits/stdc++.h>
using namespace std;
const int sz = 1e3 + 10, inf = 1e9;
int cx[sz], cy[sz], go[sz][sz], ve[sz][sz];
struct re {
  int fr, to, cap;
};
struct ot {
  int x1, y1, x2, y2;
};
int s, t, yk[sz * 2], di[sz * 2];
vector<int> sv[sz * 2];
vector<re> edges;
void add_edge(int u, int v, int cap) {
  sv[u].push_back(edges.size());
  edges.push_back({u, v, cap});
  sv[v].push_back(edges.size());
  edges.push_back({v, u, 0});
}
bool bfs(int n) {
  int qu[n], qf = 0, qb = 1;
  qu[0] = s;
  for (int a = 0; a < n; a++) di[a] = inf;
  di[s] = 0;
  while (qf < qb) {
    int v = qu[qf];
    for (int a = 0; a < sv[v].size(); a++) {
      int i = sv[v][a];
      int ne = edges[i].to;
      if (di[ne] == inf and edges[i].cap > 0) {
        di[ne] = di[v] + 1, qu[qb] = ne, qb++;
      }
    }
    qf++;
  }
  return di[t] != inf;
}
int dfs(int v, int flow) {
  if (v == t) return flow;
  while (yk[v] < sv[v].size()) {
    int i = sv[v][yk[v]];
    int ne = edges[i].to;
    if (di[ne] == di[v] + 1 and edges[i].cap > 0) {
      int re = dfs(ne, min(flow, edges[i].cap));
      if (re) {
        edges[i].cap -= re;
        edges[i ^ 1].cap += re;
        return re;
      }
    }
    yk[v]++;
  }
  return 0;
}
int dinic(int n) {
  int flow = 0;
  while (bfs(n)) {
    for (int a = 0; a < n; a++) yk[a] = 0;
    while (1) {
      int add = dfs(s, inf);
      if (add)
        flow += add;
      else
        break;
    }
  }
  return flow;
}
vector<int> sv2[sz * 2];
bool us[sz * 2], in[sz * 2];
void dfs2(int v) {
  us[v] = 1;
  for (int a = 0; a < sv2[v].size(); a++) {
    int ne = sv2[v][a];
    if (us[ne] == 0) dfs2(ne);
  }
}
int main() {
  int n, n1;
  cin >> n;
  int ar[n][2];
  map<int, int> mx, my;
  for (int a = 0; a < n; a++) {
    cin >> ar[a][0] >> ar[a][1];
    mx[ar[a][0]] = 0, my[ar[a][1]] = 0;
  }
  int qx = 0, qy = 0;
  for (auto it = mx.begin(); it != mx.end(); it++)
    cx[qx] = (*it).first, (*it).second = qx, qx++;
  for (auto it = my.begin(); it != my.end(); it++)
    cy[qy] = (*it).first, (*it).second = qy, qy++;
  for (int a = 0; a < n; a++) {
    int x = mx[ar[a][0]], y = my[ar[a][1]];
    go[y][x] = 1, ve[y][x] = 1;
  }
  int vq = 2;
  for (int a = 0; a < qy; a++) {
    vector<int> sp;
    for (int b = 0; b < qx; b++)
      if (go[a][b]) sp.push_back(b);
    for (int b = 0; b + 1 < sp.size(); b++) {
      if (sp[b] + 1 < sp[b + 1]) {
        for (int c = sp[b] + 1; c < sp[b + 1]; c++) go[a][c] = vq;
        vq++;
      }
    }
  }
  n1 = vq;
  for (int a = 0; a < qx; a++) {
    vector<int> sp;
    for (int b = 0; b < qy; b++)
      if (ve[b][a]) sp.push_back(b);
    for (int b = 0; b + 1 < sp.size(); b++) {
      if (sp[b] + 1 < sp[b + 1]) {
        for (int c = sp[b] + 1; c < sp[b + 1]; c++) ve[c][a] = vq;
        vq++;
      }
    }
  }
  for (int a = 0; a < qy; a++) {
    for (int b = 0; b < qx; b++) {
      if (go[a][b] > 1 and ve[a][b] > 1) {
        add_edge(go[a][b], ve[a][b], 1);
      }
    }
  }
  s = vq, t = vq + 1;
  for (int a = 2; a < n1; a++) {
    add_edge(s, a, 1);
  }
  for (int a = n1; a < vq; a++) {
    add_edge(a, t, 1);
  }
  vq += 2;
  int an2 = qy + qx;
  int flow = dinic(vq);
  an2 += flow;
  int matching = 0;
  for (int a = 0; a < edges.size(); a++) {
    int fr = edges[a].fr, to = edges[a].to;
    if (fr < to and max(fr, to) < s) {
      if (edges[a].cap)
        sv2[fr].push_back(to);
      else
        sv2[to].push_back(fr), in[fr] = 1, matching++;
    }
  }
  if (flow != matching) {
    cout << flow << " " << matching << " ";
    while (1) cout << 1;
  }
  bool ok[vq];
  for (int a = 0; a < n1; a++)
    if (us[a] == 0 and in[a] == 0) dfs2(a);
  ok[0] = 0;
  for (int a = 1; a < vq; a++) {
    ok[a] = 1;
    if (a < n1 and us[a] == 0) ok[a] = 0;
    if (a >= n1 and us[a]) ok[a] = 0;
  }
  vector<ot> an;
  for (int a = 0; a < qy; a++) {
    int yk = 0;
    while (yk < qx) {
      if (ok[go[a][yk]]) {
        int x1 = cx[yk], y1 = cy[a];
        while (yk < qx) {
          if (ok[go[a][yk]])
            yk++;
          else
            break;
        }
        int x2 = cx[yk - 1], y2 = cy[a];
        an.push_back({x1, y1, x2, y2});
      } else
        yk++;
    }
  }
  cout << an.size() << "\n";
  for (int a = 0; a < an.size(); a++)
    cout << an[a].x1 << " " << an[a].y1 << " " << an[a].x2 << " " << an[a].y2
         << "\n";
  int an1 = an.size();
  an.clear();
  for (int a = 0; a < qx; a++) {
    int yk = 0;
    while (yk < qy) {
      if (ok[ve[yk][a]]) {
        int x1 = cx[a], y1 = cy[yk];
        while (yk < qy) {
          if (ok[ve[yk][a]])
            yk++;
          else
            break;
        }
        int x2 = cx[a], y2 = cy[yk - 1];
        an.push_back({x1, y1, x2, y2});
      } else
        yk++;
    }
  }
  cout << an.size() << "\n";
  for (int a = 0; a < an.size(); a++)
    cout << an[a].x1 << " " << an[a].y1 << " " << an[a].x2 << " " << an[a].y2
         << "\n";
  an1 += an.size();
  if (an1 != an2)
    while (1) cout << 1;
}
