#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
const int MAXN = 30000;
const int MAXK = 200;
int n, k;
int d[MAXK][MAXN], drt[MAXK];
int rt;
int depth[MAXN];
vector<int> childs[MAXN];
int parent[MAXN];
vector<int> todo[MAXN];
int intodo[MAXN];
int mark[MAXN];
void dfsmark(int at, int val) {
  if (mark[at] != -1)
    return;
  else
    mark[at] = val;
  for (int i = (0); i < (((int)(todo[at]).size())); ++i)
    mark[todo[at][i]] = val;
  for (int i = (0); i < (((int)(childs[at]).size())); ++i)
    dfsmark(childs[at][i], val);
}
void updatetodo(int x) {
  vector<int> ntodo;
  for (int i = (0); i < (((int)(todo[x]).size())); ++i)
    if (intodo[todo[x][i]] == x) ntodo.push_back(todo[x][i]);
  todo[x] = ntodo;
}
bool solve() {
  for (int i = (0); i < (k); ++i) {
    drt[i] = -1;
    for (int j = (0); j < (n); ++j)
      if (d[i][j] == 0)
        if (drt[i] != -1)
          return false;
        else
          drt[i] = j;
    if (drt[i] == -1) return false;
  }
  rt = drt[0];
  for (int j = (0); j < (n); ++j)
    depth[j] = d[0][j], childs[j].clear(), parent[j] = -2, todo[j].clear();
  for (int j = (0); j < (n); ++j)
    if (j != rt) todo[rt].push_back(j), intodo[j] = rt;
  intodo[rt] = -1, parent[rt] = -1;
  for (int i = (1); i < (k); ++i) {
    int crt = drt[i];
    vector<int> path(depth[crt] + 1, -1);
    for (int j = (0); j < (n); ++j)
      if (d[i][j] + depth[j] == depth[crt])
        if (path[depth[j]] != -1)
          return false;
        else
          path[depth[j]] = j;
    for (int k = (0); k < (((int)(path).size())); ++k)
      if (path[k] == -1) return false;
    vector<vector<int> > subtree(depth[crt] + 1);
    for (int j = (0); j < (n); ++j) {
      if ((depth[j] + depth[crt] - d[i][j]) % 2 != 0) return false;
      int dlca = (depth[j] + depth[crt] - d[i][j]) / 2;
      if (dlca < 0 || dlca > depth[crt]) return false;
      if (j != path[dlca]) subtree[dlca].push_back(j);
    }
    int pos = depth[crt];
    while (pos >= 0 && intodo[path[pos]] != -1) --pos;
    if (pos < 0) return false;
    int mrt = path[pos];
    for (int j = (0); j < (n); ++j) mark[j] = -1;
    for (int k = pos; k >= 0; --k) {
      if (intodo[path[k]] != -1) return false;
      if (k != 0 && parent[path[k]] != path[k - 1] ||
          k == 0 && parent[path[k]] != -1)
        return false;
      dfsmark(path[k], path[k]);
    }
    for (int k = (0); k <= (pos); ++k) {
      if (mark[path[k]] != path[k]) return false;
      for (int l = (0); l < (((int)(subtree[k]).size())); ++l) {
        if (mark[subtree[k][l]] != path[k]) return false;
      }
    }
    for (int k = (pos + 1); k < (((int)(path).size())); ++k) {
      if (intodo[path[k]] != mrt) return false;
      intodo[path[k]] = -1;
      parent[path[k]] = path[k - 1];
      childs[path[k - 1]].push_back(path[k]);
      for (int l = (0); l < (((int)(subtree[k]).size())); ++l) {
        if (intodo[subtree[k][l]] != mrt) return false;
        intodo[subtree[k][l]] = path[k];
        todo[path[k]].push_back(subtree[k][l]);
      }
    }
    updatetodo(mrt);
  }
  for (int j = (0); j < (n); ++j)
    if (((int)(todo[j]).size()) > 0) {
      int dmx = depth[j];
      for (int k = (0); k < (((int)(todo[j]).size())); ++k)
        if (depth[todo[j][k]] > dmx) dmx = depth[todo[j][k]];
      vector<int> fst(dmx - depth[j] + 1, -1);
      fst[0] = j;
      for (int k = (0); k < (((int)(todo[j]).size())); ++k) {
        int cur = depth[todo[j][k]] - depth[j];
        if (cur <= 0)
          return false;
        else if (fst[cur] == -1)
          fst[cur] = todo[j][k];
      }
      for (int k = (0); k < (((int)(fst).size())); ++k)
        if (fst[k] == -1) return false;
      for (int k = (0); k < (((int)(todo[j]).size())); ++k) {
        int cur = depth[todo[j][k]] - depth[j];
        parent[todo[j][k]] = fst[cur - 1];
        childs[fst[cur - 1]].push_back(todo[j][k]);
      }
    }
  return true;
}
void run() {
  scanf("%d%d", &n, &k);
  for (int i = (0); i < (k); ++i)
    for (int j = (0); j < (n); ++j) scanf("%d", &d[i][j]);
  if (!solve()) {
    printf("-1\n");
    return;
  }
  for (int i = (0); i < (n); ++i)
    if (parent[i] != -1) printf("%d %d\n", i + 1, parent[i] + 1);
}
int main() {
  run();
  return 0;
}
