#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
const ll MOD = 1000000007;
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
ll binpow(ll a, ll b) {
  ll res = 1;
  while (b) {
    if (b & 1) res = (res * a) % MOD;
    a = (a * a) % MOD;
    b >>= 1;
  }
  return res;
}
ll modInv(ll a) { return binpow(a, MOD - 2); }
const double PI = acos(-1);
const double eps = -1e6;
const int INF = 0x3f3f3f3f;
const int NINF = 0xc0c0c0c0;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const ll NINFLL = 0xc0c0c0c0c0c0c0c0;
const int mxN = 30001;
int par[mxN][16];
int depth[mxN];
vector<int> spe[201];
int val[201];
vector<int> hang[mxN];
vector<pair<int, vector<pair<int, int>>>> rst;
vector<pair<int, int>> res;
int cnt[mxN];
bool flag[mxN];
int n, k;
void killthyself() {
  cout << "-1\n";
  exit(0);
}
void upd(int a, int p) {
  if (flag[a]) return;
  flag[a] = true;
  par[a][0] = p;
  depth[a] = depth[p] + 1;
  for (int lg = (1); lg < (16); ++lg) {
    par[a][lg] = par[par[a][lg - 1]][lg - 1];
  }
  res.push_back({a, p});
}
int walk(int a, int nh) {
  for (int i = (16) - 1; i >= (0); --i) {
    if (depth[par[a][i]] >= nh) {
      a = par[a][i];
    }
  }
  return a;
}
int lca(int a, int b) {
  if (depth[a] < depth[b]) {
    b = walk(b, depth[a]);
  } else if (depth[a] > depth[b]) {
    a = walk(a, depth[b]);
  }
  if (a == b) return a;
  for (int i = (16) - 1; i >= (0); --i) {
    if (par[a][i] != par[b][i]) {
      a = par[a][i];
      b = par[b][i];
    }
  }
  return par[a][0];
}
int dist(int a, int b) { return depth[a] + depth[b] - 2 * depth[lca(a, b)]; }
int nthonpath(int first, int second, int d) {
  int imhavingfun = lca(first, second);
  if (depth[first] - depth[imhavingfun] >= d) {
    return walk(first, depth[first] - d);
  } else {
    d -= (depth[first] - depth[imhavingfun]);
    return walk(second, depth[imhavingfun] + d);
  }
}
int main() {
  mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
  cin.tie(0)->sync_with_stdio(0);
  cin >> n >> k;
  for (int i = (0); i < (n); ++i) {
    hang[i].push_back(i);
  }
  for (int i = (0); i < (k); ++i) {
    memset(cnt, 0, sizeof(cnt));
    spe[i].resize(n);
    int mx = 0;
    for (int j = (0); j < (n); ++j) {
      cin >> spe[i][j];
      if (spe[i][j] == 0) val[i] = j;
      mx = max(mx, spe[i][j]);
      cnt[spe[i][j]]++;
    }
    int mex = -1;
    while (cnt[mex + 1]) mex++;
    if (mex != mx) killthyself();
  }
  int rt = val[0];
  for (int i = (0); i < (16); ++i) {
    par[rt][i] = rt;
  }
  flag[rt] = 1;
  for (int i = (1); i < (k); ++i) {
    vector<pair<int, int>> chain;
    for (int j = (0); j < (n); ++j) {
      if (spe[i][j] + spe[0][j] == spe[0][val[i]])
        chain.push_back({spe[0][j], j});
    }
    sort(chain.begin(), chain.end());
    int prv = -1;
    int tp = rt;
    for (int j = (0); j < (chain.size()); ++j) {
      if (chain[j].first != prv + 1) killthyself();
      prv++;
      upd(chain[j].second, tp);
      tp = chain[j].second;
    }
  }
  for (int i = (0); i < (n); ++i) {
    if (!flag[i]) {
      rst.push_back({i, {}});
      for (int j = (0); j < (k); ++j) {
        rst.back().second.push_back({spe[j][i], j});
      }
      sort(rst.back().second.begin(), rst.back().second.end());
    }
  }
  sort(
      rst.begin(), rst.end(),
      [&](pair<int, vector<pair<int, int>>> a,
          pair<int, vector<pair<int, int>>> b) { return a.second < b.second; });
  for (int i = (0); i < (rst.size()); ++i) {
    int id = rst[i].first;
    vector<pair<int, int>> stuff = rst[i].second;
    int close = val[stuff[0].second];
    pair<int, int> tohang = {0, close};
    for (int j = (1); j < (stuff.size()); ++j) {
      int far = val[stuff[j].second];
      int cc = spe[stuff[0].second][far];
      int aa = stuff[0].first;
      int bb = stuff[j].first;
      if (aa + cc == bb) continue;
      int offtree = aa + bb - cc;
      if (offtree & 1) killthyself();
      offtree >>= 1;
      tohang = max(tohang, {aa - offtree, nthonpath(close, far, aa - offtree)});
    }
    tohang.first = stuff[0].first - tohang.first - 1;
    if (hang[tohang.second].size() > tohang.first + 1) {
      upd(id, hang[tohang.second][tohang.first]);
    } else {
      hang[tohang.second].push_back(id);
      if (hang[tohang.second].size() > tohang.first + 1) {
        upd(id, hang[tohang.second][tohang.first]);
      } else {
        killthyself();
      }
    }
  }
  for (int i = (0); i < (k); ++i) {
    for (int j = (0); j < (n); ++j) {
      if (dist(val[i], j) != spe[i][j]) killthyself();
    }
  }
  for (auto p : res) {
    cout << (p.first + 1) << " " << (p.second + 1) << "\n";
  }
  return 0;
}
