#include <bits/stdc++.h>
using std::queue;
const int INF = 200000, N = 100;
int n, a[100], f[100][100], w, fa[100], m, b[100], tot, s, t, last[N],
    to[N << 2], Next[N << 2], edge, flow[N << 2];
int deep[N], sum, c[N];
queue<int> q;
char s1[100], s2[110];
struct ed {
  int x, y;
} e[100];
int cw(int x) {
  int cnt = 0;
  while (x) x = x / 10, cnt++;
  return cnt;
}
int find(int x) {
  if (fa[x] == x) return x;
  fa[x] = find(fa[x]);
  return fa[x];
}
bool p() {
  for (int i = 1; i <= w; i++) fa[i] = i;
  for (int i = 1; i <= m; i++) {
    if (b[i] == 1) {
      int fx = find(e[i].x), fy = find(e[i].y);
      if (fx == fy) return false;
      fa[fx] = fy;
    }
  }
  return true;
}
int cal(int x) { return x & 1 ? x + 1 : x - 1; }
void add(int x, int y, int z) {
  to[++edge] = y;
  Next[edge] = last[x];
  last[x] = edge;
  flow[edge] = z;
}
void Add(int x, int y, int z) { add(x, y, z), add(y, x, 0); }
bool bfs() {
  memset(deep, 0, sizeof(deep));
  deep[s] = 1;
  q.push(s);
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    for (int i = last[x]; i; i = Next[i])
      if (flow[i] && !deep[to[i]]) {
        deep[to[i]] = deep[x] + 1;
        q.push(to[i]);
      }
  }
  return deep[t];
}
int Dfs(int x, int now) {
  if (x == t) return now;
  for (int i = last[x]; i; i = Next[i]) {
    if (deep[to[i]] <= deep[x]) continue;
    if (!flow[i]) continue;
    int di = Dfs(to[i], std::min(now, flow[i]));
    if (di) {
      flow[i] -= di;
      flow[cal(i)] += di;
      return di;
    }
  }
  return 0;
}
void Printf() {
  for (int i = 1; i <= m; i++)
    if (b[i]) printf("%d %d\n", c[e[i].x], c[e[i].y]);
  for (int i = 1; i <= w; i++)
    for (int j = c[i + 1] - 1; j >= c[i + 1] - f[i][i]; j--)
      printf("%d %d\n", j, j - 1);
  for (int x = 1; x <= w; x++) {
    int now = c[x] + 1;
    for (int i = last[x]; i; i = Next[i])
      if (to[i] - w > 0 && to[i] - w <= m) {
        int u = e[to[i] - w].x + e[to[i] - w].y - x;
        for (int j = now; j < now + flow[i]; j++) printf("%d %d\n", c[u], j);
        now = now + flow[i];
      }
  }
}
void solve() {
  for (int i = 1; i <= m; i++) f[e[i].x][e[i].y] -= b[i];
  memset(last, 0, sizeof(last));
  edge = 0;
  for (int i = 1; i <= w; i++) Add(i, t, a[i] - 1 - f[i][i]);
  for (int i = 1; i <= m; i++)
    if (f[e[i].x][e[i].y]) {
      Add(i + w, e[i].x, INF);
      Add(i + w, e[i].y, INF);
      Add(s, i + w, f[e[i].x][e[i].y]);
    }
  int ans = 0;
  while (bfs())
    while (int di = Dfs(s, INF)) ans += di;
  if (ans == sum) {
    Printf();
    exit(0);
  }
  for (int i = 1; i <= m; i++) f[e[i].x][e[i].y] += b[i];
}
void dfs(int x, int y) {
  if (y == w - 1) {
    if (p()) solve();
    return;
  }
  if (x > m) return;
  b[x] = 0, dfs(x + 1, y);
  if (f[e[x].x][e[x].y]) b[x] = 1, dfs(x + 1, y + 1);
}
int main() {
  scanf("%d", &n);
  w = cw(n);
  for (int i = 1; i < n; i++) {
    scanf("%s%s", &s1, &s2);
    int w1 = strlen(s1), w2 = strlen(s2);
    if (w1 > w2) std::swap(w1, w2);
    f[w1][w2]++;
  }
  int j = 1;
  for (int i = 1; i < w; i++, j = j * 10) a[i] = j * 9, c[i] = j;
  if (w == 1)
    a[w] = n;
  else
    a[w] = n - j + 1;
  c[w + 1] = n + 1;
  c[w] = j;
  sum = n - 1 - (w - 1);
  for (int i = 1; i <= w; i++)
    if (f[i][i] >= a[i]) {
      puts("-1");
      return 0;
    } else
      sum -= f[i][i];
  m = 0;
  for (int i = 1; i <= w; i++)
    for (int j = i + 1; j <= w; j++) e[++m] = {i, j};
  s = w + m + 1, t = w + m + 2;
  dfs(1, 0);
  puts("-1");
  return 0;
}
