#include <bits/stdc++.h>
const int N = 30005, K = 205;
int n, k, dis[K][N], id[K];
int f[15][N];
bool important[N], marked[N], leaf[N];
void ________(bool x) {
  if (!x) std::cout << "-1\n", std::exit(0);
}
std::vector<int> graph[N];
void link(int x, int y) {
  graph[x].emplace_back(y), graph[y].emplace_back(x);
  f[0][x] = y;
}
int jump(int x, int d) {
  for (int i = 0; i < 15; ++i)
    if (d >> i & 1) x = f[i][x];
  return x;
}
std::vector<int> chain[N];
int d[N];
bool vis[N];
void bfs(int x) {
  std::memset(vis + 1, 0, n), d[x] = 0;
  std::queue<int> q;
  q.push(x), vis[x] = 1;
  while (q.size()) {
    int x = q.front();
    q.pop();
    for (int t : graph[x])
      if (!vis[t]) d[t] = d[x] + 1, vis[t] = 1, q.push(t);
  }
}
int main() {
  std::ios::sync_with_stdio(0), std::cin.tie(0);
  std::cin >> n >> k;
  for (int i = 1; i <= k; ++i) {
    for (int j = 1; j <= n; ++j) std::cin >> dis[i][j];
    ________(std::count(dis[i] + 1, dis[i] + n + 1, 0) == 1);
    id[i] = std::find(dis[i] + 1, dis[i] + n + 1, 0) - dis[i];
    ________(!important[id[i]]), important[id[i]] = 1, leaf[id[i]] = 1;
  }
  int root = id[1], *dep = dis[1];
  for (int i = 2; i <= k; ++i) {
    std::vector<int> vertices;
    for (int j = 1; j <= n; ++j)
      if (dep[j] + dis[i][j] == dep[id[i]]) vertices.emplace_back(j);
    std::sort(vertices.begin(), vertices.end(),
              [&](int x, int y) { return dep[x] < dep[y]; });
    for (int j = 1; j < vertices.size(); ++j) {
      int p = vertices[j], f = vertices[j - 1];
      ________(dep[p] == dep[f] + 1), leaf[f] = 0;
      if (!marked[p]) marked[p] = 1, link(p, f);
    }
  }
  for (int i = 1; i < 15; ++i)
    for (int j = 1; j <= n; ++j) f[i][j] = f[i - 1][f[i - 1][j]];
  marked[root] = 1;
  std::vector<int> unsure, leaves;
  for (int i = 1; i <= n; ++i)
    if (!marked[i]) unsure.emplace_back(i);
  std::sort(unsure.begin(), unsure.end(),
            [&](int x, int y) { return dep[x] < dep[y]; });
  for (int i = 1; i <= n; ++i)
    if (marked[i]) chain[i].emplace_back(i);
  for (int i = 1; i <= k; ++i)
    if (leaf[id[i]]) leaves.emplace_back(i);
  leaves.emplace_back(1);
  for (int p : unsure) {
    int found = 0, _dep = 0;
    bool ok = 0;
    for (int k : leaves)
      if (k != 1)
        if (dep[id[k]] + dis[k][p] == dep[p]) {
          ________(chain[id[k]].size() >= dis[k][p]);
          link(p, chain[id[k]][dis[k][p] - 1]), ok = 1;
          if (chain[id[k]].size() == dis[k][p]) chain[id[k]].emplace_back(p);
        }
    if (ok) continue;
    for (int k : leaves)
      if (std::abs(dep[p] - dis[k][p]) < dep[id[k]]) {
        int up = dep[id[k]] + dis[k][p] - dep[p] >> 1;
        if (dep[id[k]] - up > _dep) {
          found = k, _dep = dep[id[k]] - up;
        }
      }
    if (found) {
      int up = dep[id[found]] + dis[found][p] - dep[p];
      ________(!(up & 1)), up >>= 1;
      int q = jump(id[found], up);
      ________(q);
      ________(chain[q].size() >= dep[p] - dep[q]);
      link(p, chain[q][dep[p] - dep[q] - 1]);
      if (chain[q].size() == dep[p] - dep[q]) chain[q].emplace_back(p);
    } else {
      ________(chain[root].size() >= dep[p]);
      link(p, chain[root][dep[p] - 1]);
      if (chain[root].size() == dep[p]) chain[root].emplace_back(p);
    }
  }
  for (int i = 1; i <= k; ++i) {
    bfs(id[i]);
    for (int j = 1; j <= n; ++j) ________(d[j] == dis[i][j]);
  }
  for (int i = 1; i <= n; ++i)
    for (int j : graph[i])
      if (i < j) std::cout << i << ' ' << j << '\n';
  return 0;
}
