#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int x = 0, f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar())
    if (c == '-') f = -1;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  return x * f;
}
const int MAXN = 100010;
const int INF = 2147483600;
int N, K;
int Node[MAXN << 1], Next[MAXN + 1], Root[MAXN + 1], cnt;
int U[MAXN + 1], V[MAXN + 1];
pair<int, int> sta[MAXN + 1];
vector<int> vec[MAXN + 1];
int s[210][30100], s1[210][30100];
inline void insert(int u, int v) {
  if (u == -1 || v == -1) {
    puts("-1");
    exit(0);
  }
  Node[++cnt] = v;
  Next[cnt] = Root[u];
  Root[u] = cnt;
  U[cnt] = u;
  V[cnt] = v;
}
int top;
int nod;
int hv, tim;
int pos[MAXN + 1], chs[5];
int Len[MAXN + 1];
int Id[MAXN + 1], root[MAXN + 1];
int pt[MAXN + 1];
inline void Divide(int n, int last) {
  hv = 0;
  ++tim;
  if (last) chs[++hv] = last;
  for (int i = 0, sz = vec[n].size(); i < sz; i++) {
    int v = vec[n][i];
    if (pos[v] && v != last) chs[++hv] = v;
    if (hv >= 2) break;
  }
  if (hv == 1) {
    int ln = pos[chs[1]];
    top = 0;
    for (int i = 0, sz = vec[n].size(); i < sz; i++) {
      int v = vec[n][i];
      sta[++top] = make_pair(s[ln][v], v);
    }
    sort(sta + 1, sta + top + 1);
    int dt = -1;
    for (int i = 2; i <= top; i++) {
      if (sta[i].first != sta[i - 1].first) {
        if (sta[i].first - sta[i - 1].first > 1) {
          puts("-1");
          exit(0);
        }
        dt = sta[i - 1].second;
      }
      insert(sta[i].second, dt);
      insert(dt, sta[i].second);
    }
    return;
  }
  int A = pos[chs[1]], B = pos[chs[2]];
  if (s[A][chs[2]] != s[B][chs[1]]) {
    puts("-1");
    exit(0);
  }
  int len = s[A][chs[2]];
  for (int i = 0, sz = vec[n].size(); i < sz; i++) {
    int v = vec[n][i];
    if (s[A][v] + s[B][v] == len) Len[s[A][v]] = tim, pt[s[A][v]] = v;
  }
  for (int i = 0; i <= len; i++) {
    if (Len[i] != tim) {
      puts("-1");
      exit(0);
    }
  }
  int dt = nod;
  for (int i = 0; i <= len; i++) Id[i] = ++nod;
  for (int i = 1; i <= len; i++)
    insert(pt[i - 1], pt[i]), insert(pt[i], pt[i - 1]), pos[pt[i]] = A;
  for (int i = 0, sz = vec[n].size(); i < sz; i++) {
    int v = vec[n][i];
    int bel = (s[A][v] - s[B][v] + len) / 2;
    s[A][v] -= bel;
    vec[Id[bel]].push_back(v);
  }
  vec[n].clear();
  for (int i = 0; i <= len; i++) vec[n].push_back(pt[i]);
  for (int i = dt + 1; i <= dt + len + 1; i++) Divide(i, vec[n][i - dt - 1]);
  return;
}
inline void dfs(int n, int k, int Fa, int de) {
  if (s[n][k] != de) {
    puts("-1");
    exit(0);
  }
  for (int x = Root[k]; x; x = Next[x]) {
    int v = Node[x];
    if (v == Fa) continue;
    dfs(n, v, k, de + 1);
  }
  return;
}
int main() {
  N = read(), K = read();
  for (int i = 1; i <= K; i++) {
    int num = 0, post = 0;
    for (int j = 1; j <= N; j++) {
      s1[i][j] = s[i][j] = read();
      if (!s[i][j]) ++num, post = j;
    }
    if (num != 1) {
      puts("-1");
      return 0;
    }
    pos[post] = i;
    root[i] = post;
  }
  for (int i = 1; i <= N; i++) vec[1].push_back(i);
  nod = 1;
  Divide(1, 0);
  memcpy(s, s1, sizeof(s));
  for (int i = 1; i <= K; i++) {
    dfs(i, root[i], 0, 0);
  }
  for (int i = 1; i <= cnt; i += 2) {
    printf("%d %d\n", U[i], V[i]);
  }
  return 0;
}
