#include <bits/stdc++.h>
using namespace std;
char s1[10], s2[10];
int n, x[200005], ee, f1[10], f2[10],
    Cnt = 1, tot, sy, y[200005], M[10], dis[500], cnt, g[10], t, p[10][10],
    c[10][10], to[500], node[500], val[500], nxt[500], cur[500];
queue<int> q;
void ADD(int x, int y, int v) {
  to[++Cnt] = y;
  nxt[Cnt] = node[x];
  node[x] = Cnt;
  val[Cnt] = v;
}
void add(int x, int y, int v) { ADD(x, y, v), ADD(y, x, 0); }
bool bfs() {
  memset(dis, -1, sizeof(dis));
  q.push(0);
  dis[0] = 0;
  int x, i;
  while (q.size()) {
    x = q.front();
    q.pop();
    for (i = node[x]; i; i = nxt[i]) {
      if (val[i] && !~dis[to[i]]) {
        dis[to[i]] = dis[x] + 1, q.push(to[i]);
      }
    }
  }
  return ~dis[t];
}
int dfs(int now, int flow) {
  if (now == t) return flow;
  int fl = 0, qwq;
  for (int &i = cur[now]; i; i = nxt[i]) {
    if (val[i] && dis[to[i]] == dis[now] + 1) {
      qwq = dfs(to[i], min(flow, val[i]));
      flow -= qwq;
      fl += qwq;
      val[i] -= qwq;
      val[i ^ 1] += qwq;
      if (!flow) break;
    }
  }
  return fl;
}
int dinic() {
  int ret = 0;
  while (bfs()) memcpy(cur, node, sizeof(cur)), ret += dfs(0, 200005);
  return ret;
}
int i, l1, l2, j, k;
int main() {
  scanf("%d", &n);
  g[1] = 1;
  g[2] = 10;
  g[3] = 100;
  g[4] = 1000;
  g[5] = 10000;
  g[6] = 100000;
  g[7] = 1000000;
  for (i = 1; i <= 6; ++i) M[i] = min(n, g[i + 1] - 1) - min(n, g[i] - 1);
  for (i = 1; i < n; ++i) {
    scanf("%s%s", s1, s2);
    l1 = strlen(s1);
    l2 = strlen(s2);
    if (l1 > l2) swap(l1, l2);
    ++c[l1][l2];
  }
  for (i = 1; i <= 6; ++i) {
    if (M[i] && c[i][i] >= M[i]) return cout << "-1", 0;
    if (c[i][i]) {
      while (c[i][i]) {
        x[++cnt] = g[i];
        --M[i];
        y[cnt] = g[i] + M[i];
        --c[i][i];
      }
    }
    sy += M[i];
  }
  for (i = 1; i < 6; ++i)
    for (j = i + 1; j <= 6; ++j) p[i][j] = ++tot;
  for (int ii = 1; ii <= 6; ++ii) {
    if (M[ii]) {
      --M[ii];
      Cnt = 1;
      memset(node, 0, sizeof(node));
      for (i = 1; i < 6; ++i) {
        for (j = i + 1; j <= 6; ++j) {
          add(p[i][j], i + tot, c[i][j]);
          add(p[i][j], j + tot, c[i][j]);
          add(0, p[i][j], c[i][j]);
        }
      }
      t = tot + 7;
      for (i = 1; i <= 6; ++i) add(i + tot, t, M[i]);
      ++M[ii];
      i = dinic();
      if (i != sy - 1) return cout << "-1", 0;
    }
  }
  tot = 0;
  for (i = 1; i < 6; ++i) {
    for (j = i + 1; j <= 6; ++j) {
      ++tot;
      if (c[i][j]) {
        for (ee = 0, k = node[tot]; k; k = nxt[k])
          if (to[k]) f1[++ee] = to[k], f2[ee] = val[k ^ 1];
        f1[1] -= 15;
        f1[2] -= 15;
        while (f2[1]) {
          --M[f1[1]];
          x[++cnt] = g[f1[1]] + M[f1[1]];
          y[cnt] = g[f1[2]];
          --f2[1];
        }
        while (f2[2]) {
          --M[f1[2]];
          x[++cnt] = g[f1[2]] + M[f1[2]];
          y[cnt] = g[f1[1]];
          --f2[2];
        }
      }
    }
  }
  for (i = 1; i <= cnt; ++i) cout << x[i] << " " << y[i] << "\n";
}
