#include <bits/stdc++.h>
template <typename T>
inline void read(T &x) {
  x = 0;
  char c = getchar();
  while (!isdigit(c)) c = getchar();
  while (isdigit(c)) x = x * 10 + (c ^ 48), c = getchar();
}
using namespace std;
const int inf = 1e9;
int n, ntot, cnt[12], nw[12];
int bpe[12][12];
int nwe[12][12];
struct Edge {
  int u, v;
} E[12 * 12];
int Etot;
inline void AddEdge(int u, int v) {
  if (u > v) swap(u, v);
  E[++Etot] = (Edge){u, v};
  --nwe[u][v];
}
int pf[12], d[12];
struct edge {
  int nxt, to, val;
} e[11000];
int head[123], hcur[123], ecnt, s, t;
inline void addedge(int from, int to, int val) {
  e[++ecnt] = (edge){head[from], to, val};
  head[from] = ecnt;
}
inline void Addedge(int u, int v, int w) { addedge(u, v, w), addedge(v, u, 0); }
int que[123], front, rear, dep[123];
inline bool bfs() {
  front = rear = 0;
  for (int i = 1; i <= t; ++i) hcur[i] = head[i];
  memset(dep, 0x3f, sizeof(dep));
  que[++rear] = s;
  dep[s] = 0;
  while (front < rear) {
    int cur = que[++front];
    for (int i = head[cur]; i; i = e[i].nxt) {
      int to = e[i].to;
      if (!e[i].val || dep[to] <= 11000) continue;
      que[++rear] = to;
      dep[to] = dep[cur] + 1;
    }
  }
  return dep[t] <= 123;
}
int dfs(int cur, int limi) {
  if (cur == t || !limi) return limi;
  int flow = 0;
  for (int i = hcur[cur]; i; i = e[i].nxt) {
    int to = e[i].to;
    hcur[cur] = i;
    if (dep[to] != dep[cur] + 1) continue;
    int tmp = dfs(to, min(e[i].val, limi));
    if (!tmp) continue;
    flow += tmp;
    limi -= tmp;
    e[i].val -= tmp;
    e[i ^ 1].val += tmp;
    if (!limi) break;
  }
  return flow;
}
int mp[12][12], mtot;
int biao[12];
inline int Get(int u, int v) {
  int tar = u < v ? mp[u][v] : mp[v][u];
  for (int i = head[u]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (to != tar) continue;
    return inf - e[i].val;
  }
  return -1;
}
inline void get_ans() {
  for (int i = 1, t = 1; i <= ntot; ++i, t = t * 10) nw[i] = t, biao[i] = t;
  for (int i = 1; i <= Etot; ++i) {
    int u = E[i].u, v = E[i].v;
    printf("%d %d\n", nw[u], nw[v]);
  }
  for (int i = 1; i <= ntot; ++i) {
    for (int j = 1; j <= ntot; ++j) {
      int ct = Get(i, j);
      for (int jzp = 1; jzp <= ct; ++jzp) {
        printf("%d %d\n", ++nw[i], biao[j]);
      }
    }
  }
}
inline void Flow() {
  memset(head, 0, sizeof(head));
  memset(hcur, 0, sizeof(hcur));
  ecnt = 1;
  mtot = ntot;
  for (int i = 1; i <= ntot; ++i) {
    for (int j = i; j <= ntot; ++j) {
      mp[i][j] = ++mtot;
    }
  }
  s = mtot + 1, t = s + 1;
  for (int i = 1; i <= ntot; ++i) Addedge(s, i, cnt[i] - 1);
  for (int i = 1; i <= ntot; ++i) {
    for (int j = i; j <= ntot; ++j) {
      if (nwe[i][j] < 0) return;
      Addedge(mp[i][j], t, nwe[i][j]);
    }
  }
  for (int i = 1; i <= ntot; ++i) {
    for (int j = 1; j <= ntot; ++j) {
      Addedge(i, i < j ? mp[i][j] : mp[j][i], inf);
    }
  }
  int flow = 0;
  while (bfs()) {
    flow += dfs(s, inf);
  }
  if (flow < n - ntot) return;
  get_ans();
  exit(0);
}
inline void work() {
  memset(d, 0, sizeof(d));
  memcpy(nwe, bpe, sizeof(bpe));
  memset(nw, 0, sizeof(nw));
  Etot = 0;
  for (int i = 1; i <= ntot - 2; ++i) ++d[pf[i]];
  for (int jzp = 1; jzp <= ntot - 2; ++jzp) {
    int id = -1;
    for (int j = 1; j <= ntot; ++j)
      if (d[j] == 0) {
        id = j;
        break;
      }
    AddEdge(id, pf[jzp]);
    --d[pf[jzp]];
    --d[id];
  }
  int jzp = 0;
  for (int j = 1; j <= ntot; ++j)
    if (d[j] == 0) {
      if (!jzp)
        jzp = j;
      else
        AddEdge(jzp, j);
    }
  Flow();
}
void dfs(int cur) {
  if (cur == ntot - 1) return work(), void();
  for (int i = 1; i <= ntot; ++i) {
    pf[cur] = i;
    dfs(cur + 1);
  }
}
int main() {
  read(n);
  if (n <= 9) {
    for (int i = 1; i < n; ++i) printf("%d %d\n", i, i + 1);
    return 0;
  }
  for (int i = 1; i < n; ++i) {
    char st1[10], st2[10];
    scanf("%s", st1);
    scanf("%s", st2);
    int len1 = strlen(st1), len2 = strlen(st2);
    if (len1 > len2) swap(len1, len2);
    ++bpe[len1][len2];
  }
  for (int i = 1, t = 1; t <= n; ++i, t = t * 10) {
    ntot = i, cnt[i] = t * 9;
    if (t * 10 > n) cnt[i] = n - t + 1;
  }
  dfs(1);
  puts("-1");
  return 0;
}
