#include <bits/stdc++.h>
using namespace std;
int n, m, cal[300000], num[300000], cur[300000];
int tot, mark[7][7], rec[7][7], lev[300000];
int S, T, Q[300000], d[300000], deg[300000];
char s1[300000], s2[300000];
priority_queue<int, vector<int>, greater<int> > q;
int read() {
  int x = 0, k = 1;
  char c;
  c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-') k = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
  return x * k;
}
struct edge {
  int cnp, to[300000], last[300000], head[300000], f[300000], F[300000];
  edge() { cnp = 2; }
  void add(int u, int v, int fl) {
    to[cnp] = v, f[cnp] = F[cnp] = fl, last[cnp] = head[u], head[u] = cnp++;
    to[cnp] = u, f[cnp] = F[cnp] = 0, last[cnp] = head[v], head[v] = cnp++;
  }
} E1;
struct node {
  int u, v;
} id[300000];
bool bfs() {
  queue<int> q;
  memset(lev, 0, sizeof(lev));
  lev[S] = 1;
  q.push(S);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int i = E1.head[u]; i; i = E1.last[i]) {
      int v = E1.to[i];
      if (E1.f[i] && !lev[v]) {
        lev[v] = lev[u] + 1;
        q.push(v);
      }
    }
    if (lev[T]) return 1;
  }
  return 0;
}
int dfs(int u, int nf) {
  if (u == T || !nf) return nf;
  int tf = 0;
  for (int i = E1.head[u]; i; i = E1.last[i]) {
    int v = E1.to[i];
    if (!E1.f[i] || lev[v] != lev[u] + 1) continue;
    int af = dfs(v, min(E1.f[i], nf));
    tf += af, nf -= af;
    E1.f[i] -= af, E1.f[i ^ 1] += af;
  }
  return tf;
}
int dinic() {
  int nf = 0;
  while (bfs()) nf += dfs(S, 9999999);
  return nf;
}
void dfs2(int u) {
  for (int i = E1.head[u]; i; i = E1.last[i]) {
    int v = E1.to[i];
    if (!E1.f[i ^ 1]) continue;
    if (u > m && u <= tot + m && v >= 1 && v <= m)
      for (int j = 1; j <= E1.f[i ^ 1]; j++) {
        int t = u - m;
        t = (id[t].u == v) ? id[t].v : id[t].u;
        printf("%d %d\n", num[t], cur[v]++);
      }
    if (u == S) dfs2(v);
  }
}
void Search(int now) {
  if (now >= m - 1) {
    int t = 1;
    for (int i = 1; i <= m; i++) d[i] = deg[i];
    for (int i = 1; i <= m; i++)
      if (!d[i]) q.push(i);
    memset(mark, 0, sizeof(mark));
    while (!q.empty() && t <= m - 2) {
      int u = q.top();
      q.pop();
      int x = u, y = Q[t];
      if (x > y) swap(x, y);
      mark[x][y] = 1;
      d[Q[t]]--;
      if (!d[Q[t]]) q.push(Q[t]);
      t++;
    }
    if (q.size() >= 2) {
      int x = q.top();
      q.pop();
      int y = q.top();
      q.pop();
      mark[x][y] = 1;
    } else if (q.size() >= 1)
      q.pop();
    for (int i = 2; i < E1.cnp; i++) E1.f[i] = E1.F[i];
    for (int i = E1.head[S]; i; i = E1.last[i]) {
      int v = E1.to[i];
      if (!v) continue;
      v -= m;
      int x = id[v].u, y = id[v].v;
      if (x > y) swap(x, y);
      E1.f[i] -= mark[x][y];
      if (E1.f[i] < 0) return;
    }
    if (dinic() == n - m) {
      for (int i = 1; i <= m; i++)
        for (int j = i + 1; j <= m; j++)
          if (mark[i][j]) printf("%d %d\n", num[i], num[j]);
      for (int i = 1; i <= m; i++) cur[i]++;
      dfs2(S);
      exit(0);
    }
    return;
  }
  for (int i = 1; i <= m; i++) deg[i]++, Q[now] = i, Search(now + 1), deg[i]--;
}
int main() {
  n = read();
  int t = n;
  while (t) {
    m++;
    t /= 10;
  }
  for (int i = 1, l = 1; i <= m; l *= 10, i++) num[i] = cur[i] = l;
  for (int i = 1, l = 1; i < m; l *= 10, i++) cal[i] = l * 10 - num[i];
  cal[m] = n - num[m] + 1;
  S = 0, T = m * m + m + 3;
  for (int i = 1; i < n; i++) {
    scanf("%s%s", s1 + 1, s2 + 1);
    int l1 = strlen(s1 + 1), l2 = strlen(s2 + 1);
    if (l1 > l2) swap(l1, l2);
    rec[l1][l2]++;
  }
  for (int i = 1; i <= m; i++)
    for (int j = i; j <= m; j++) {
      id[++tot].u = i, id[tot].v = j;
      E1.add(S, tot + m, rec[i][j]);
      E1.add(tot + m, i, 9999999);
      E1.add(tot + m, j, 9999999);
    }
  for (int i = 1; i <= m; i++) E1.add(i, T, cal[i] - 1);
  Search(1);
  printf("-1\n");
  return 0;
}
