#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline bool chkmax(T &x, const T &y) {
  return x < y ? x = y, 1 : 0;
}
template <typename T>
inline bool chkmin(T &x, const T &y) {
  return x > y ? x = y, 1 : 0;
}
struct IO {
  static const int maxn = (1 << 26) + 10;
  char a[maxn], *s, b[5], *t;
  void INPUT() {
    s = a;
    t = b;
    a[fread(a, 1, sizeof a, stdin)] = 0;
  }
  void OUTPUT() { fwrite(b, 1, t - b, stdout); }
  operator int() {
    int x = 0;
    while (*s != '-' && (*s < '0' || *s > '9')) {
      ++s;
    }
    bool f = 0;
    if (*s == '-') {
      f = 1;
      ++s;
    }
    while (*s >= '0' && *s <= '9') {
      (x *= 10) += *s - '0';
      ++s;
    }
    if (f) {
      x = -x;
    }
    return x;
  }
  operator long long() {
    long long x = 0;
    while (*s != '-' && (*s < '0' || *s > '9')) {
      ++s;
    }
    bool f = 0;
    if (*s == '-') {
      f = 1;
      ++s;
    }
    while (*s >= '0' && *s <= '9') {
      (x *= 10) += *s - '0';
      ++s;
    }
    if (f) {
      x = -x;
    }
    return x;
  }
  operator char() {
    while (*s <= 32) {
      ++s;
    }
    char ret = *s;
    ++s;
    return ret;
  }
  inline void out(int x) {
    if (!x) {
      *t++ = '0';
      return;
    }
    if (x < 0) {
      *t++ = '-';
      x = -x;
    }
    static char c[20], *i;
    i = c;
    while (x) {
      int y = x / 10;
      *i++ = x - y * 10 + '0';
      x = y;
    }
    while (i != c) {
      *t++ = *--i;
    }
    return;
  }
  inline void out(int x, char C) {
    if (!x) {
      *t++ = '0';
      *t++ = C;
      return;
    }
    if (x < 0) {
      *t++ = '-';
      x = -x;
    }
    static char c[20], *i;
    i = c;
    while (x) {
      int y = x / 10;
      *i++ = x - y * 10 + '0';
      x = y;
    }
    while (i != c) {
      *t++ = *--i;
    }
    *t++ = C;
    return;
  }
  inline void out(long long x) {
    if (!x) {
      *t++ = '0';
      return;
    }
    if (x < 0) {
      *t++ = '-';
      x = -x;
    }
    static char c[20], *i;
    i = c;
    while (x) {
      long long y = x / 10;
      *i++ = x - y * 10 + '0';
      x = y;
    }
    while (i != c) {
      *t++ = *--i;
    }
    return;
  }
  inline void out(long long x, char C) {
    if (!x) {
      *t++ = '0';
      *t++ = C;
      return;
    }
    if (x < 0) {
      *t++ = '-';
      x = -x;
    }
    static char c[20], *i;
    i = c;
    while (x) {
      long long y = x / 10;
      *i++ = x - y * 10 + '0';
      x = y;
    }
    while (i != c) {
      *t++ = *--i;
    }
    *t++ = C;
    return;
  }
  inline void out(char c) {
    *t++ = c;
    return;
  }
  inline void out(char *s) {
    while (*s >= ' ') {
      *t++ = *s++;
    }
    return;
  }
} io;
void Main();
int main(int argc, char *argv[]) {
  io.INPUT();
  Main();
  io.OUTPUT();
  return 0;
}
const int maxn = 3e4 + 10;
const int maxm = 210;
int n, m;
int d[maxm][maxn], id[maxm], fuck[maxn], par[maxn], dep[maxn], R[maxn];
bool f[maxn];
set<pair<int, int> > ans;
vector<pair<int, int> > has[maxn];
vector<pair<int, pair<int, int> > > Has[maxn];
vector<int> g[maxn], gg[maxn];
void dfs1(int u, int p = 0) {
  for (int v : gg[u]) {
    if (v != p) {
      dep[v] = dep[u] + 1;
      dfs1(v, u);
    }
  }
  return;
}
void dfs2(int u, int p = 0) {
  R[dep[u]] = u;
  for (auto x : Has[u]) {
    has[R[x.first]].push_back(x.second);
  }
  for (int v : gg[u]) {
    if (v != p) {
      dfs2(v, u);
    }
  }
  return;
}
bool check(int u, int dep, int *d, int par = 0) {
  if (dep != d[u]) {
    return 0;
  }
  for (int v : g[u]) {
    if (v != par) {
      if (!check(v, dep + 1, d, u)) {
        return 0;
      }
    }
  }
  return 1;
}
int F(int u) { return par[u] == u ? u : par[u] = F(par[u]); }
void add(int u, int v) {
  ;
  if (u > v) {
    swap(u, v);
  }
  ans.insert(make_pair(u, v));
}
void Main() {
  n = io;
  m = io;
  for (int i = 0, i_end_ = (m); i < i_end_; ++i) {
    for (int j = (1), j_end_ = (n); j <= j_end_; ++j) {
      d[i][j] = io;
      if (!d[i][j]) {
        if (id[i]) {
          puts("-1");
          return;
        }
        id[i] = j;
      }
    }
    if (!id[i]) {
      puts("-1");
      return;
    }
  }
  if (m == 1) {
    vector<pair<int, int> > all;
    for (int u = (1), u_end_ = (n); u <= u_end_; ++u) {
      all.push_back(make_pair(d[0][u], u));
    }
    sort((all).begin(), (all).end());
    for (int i = (1), i_end_ = (n - 1); i <= i_end_; ++i) {
      if (all[i].first - all[i - 1].first > 1) {
        puts("-1");
        return;
      }
    }
    int rem = id[0];
    for (int i = (1), i_end_ = (n - 1); i <= i_end_; ++i) {
      printf("%d %d\n", all[i].second, rem);
      if (i < n - 1 && all[i + 1].first != all[i].first) {
        rem = all[i].second;
      }
    }
    return;
  }
  int cnt = 0;
  for (int u = (1), u_end_ = (n); u <= u_end_; ++u) {
    par[u] = u;
  }
  for (int i = 0, i_end_ = (m - 1); i < i_end_; ++i) {
    int len = d[i][id[i + 1]];
    memset(fuck, 0, sizeof fuck);
    for (int u = (1), u_end_ = (n); u <= u_end_; ++u) {
      if (d[i][u] + d[i + 1][u] == len) {
        if (fuck[d[i][u]]) {
          puts("-1");
          return;
        }
        fuck[d[i][u]] = u;
        cnt += (!f[u]);
        f[u] = 1;
      }
    }
    for (int j = (1), j_end_ = (len); j <= j_end_; ++j) {
      add(fuck[j - 1], fuck[j]);
      par[F(fuck[j - 1])] = F(fuck[j]);
    }
  }
  for (auto x : ans) {
    gg[x.first].push_back(x.second);
    gg[x.second].push_back(x.first);
  }
  if ((int)((ans).size()) != cnt - 1) {
    puts("-1");
    return;
  }
  int ffuck = F(id[0]);
  for (int i = (1), i_end_ = (m - 1); i <= i_end_; ++i) {
    if (F(id[i]) != ffuck) {
      puts("-1");
      return;
    }
  }
  dfs1(id[0]);
  for (int u = (1), u_end_ = (n); u <= u_end_; ++u) {
    if (!f[u]) {
      int mx = -1, rem = -1;
      pair<int, int> fuck;
      for (int i = (1), i_end_ = (m - 1); i <= i_end_; ++i) {
        int du = d[0][u], v = id[i], dv = dep[v], duv = d[i][u];
        if (du + dv < duv || (du + dv - duv & 1)) {
          puts("-1");
          return;
        }
        int x = du + dv - duv >> 1;
        if (x > du || x > dv) {
          puts("-1");
          return;
        }
        if (x > mx) {
          mx = x;
          rem = v;
          fuck = make_pair(du - x, u);
        }
      }
      if (!~rem) {
        puts("-1");
        return;
      }
      Has[rem].push_back(make_pair(mx, fuck));
    }
  }
  dfs2(id[0]);
  for (int u = (1), u_end_ = (n); u <= u_end_; ++u) {
    if (f[u]) {
      has[u].push_back(make_pair(0, u));
      sort((has[u]).begin(), (has[u]).end());
      for (int i = (1), i_end_ = ((int)((has[u]).size()) - 1); i <= i_end_;
           ++i) {
        if (has[u][i].first - has[u][i - 1].first > 1) {
          puts("-1");
          return;
        }
      }
      int rem;
      for (int i = (1), i_end_ = ((int)((has[u]).size()) - 1); i <= i_end_;
           ++i) {
        if (has[u][i].first - has[u][i - 1].first == 1) {
          rem = has[u][i - 1].second;
        }
        add(rem, has[u][i].second);
        par[F(rem)] = F(has[u][i].second);
      }
    }
  }
  if ((int)((ans).size()) != n - 1) {
    puts("-1");
    return;
  }
  ffuck = F(1);
  for (int i = (2), i_end_ = (n); i <= i_end_; ++i) {
    if (F(i) != ffuck) {
      puts("-1");
      return;
    }
  }
  for (auto x : ans) {
    g[x.first].push_back(x.second);
    g[x.second].push_back(x.first);
  }
  for (int i = 0, i_end_ = (m); i < i_end_; ++i) {
    if (!check(id[i], 0, d[i])) {
      puts("-1");
      return;
    }
  }
  for (auto x : ans) {
    printf("%d %d\n", x.first, x.second);
  }
  return;
}
