#include <bits/stdc++.h>
using namespace std;
class UnionFind {
 private:
  unsigned size_;
  std::vector<unsigned> par, rank;

 public:
  UnionFind()
      : size_(0), par(std::vector<unsigned>()), rank(std::vector<unsigned>()){};
  UnionFind(unsigned size__) : size_(size__) {
    par.resize(size_);
    rank.resize(size_);
    for (unsigned i = 0; i < size_; i++) par[i] = i, rank[i] = 0;
  }
  unsigned size() { return size_; }
  unsigned root(unsigned x) { return par[x] == x ? x : par[x] = root(par[x]); }
  bool same(unsigned x, unsigned y) { return root(x) == root(y); }
  void unite(unsigned x, unsigned y) {
    x = root(x), y = root(y);
    if (x == y) return;
    if (rank[x] < rank[y])
      par[x] = y;
    else if (rank[x] == rank[y])
      par[y] = x, rank[x]++;
    else
      par[y] = x;
  }
  bool operator==(const UnionFind &u) { return par == u.par; }
  bool operator!=(const UnionFind &u) { return par != u.par; }
};
vector<tuple<int, int, int>> tup;
int n, m;
int main() {
  while (true) {
    cin >> n >> m;
    if (n == 0 && m == 0) break;
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        int a;
        cin >> a;
        if (a >= 1) tup.push_back(make_tuple(a, i, n + j));
      }
    }
    for (int i = 0; i < m; i++) {
      for (int j = i + 1; j < m; j++) {
        int a;
        cin >> a;
        if (a >= 1) tup.push_back(make_tuple(a, n + i, n + j));
      }
    }
    sort(tup.begin(), tup.end());
    UnionFind UF(n + m);
    int cnt = 0, G = 0;
    for (int i = 0; i < tup.size(); i++) {
      int a1 = get<1>(tup[i]), a2 = get<2>(tup[i]);
      if (UF.same(a1, a2) == false) {
        UF.unite(a1, a2);
        cnt += get<0>(tup[i]);
        G++;
      }
      if (G == m) {
        break;
      }
    }
    cout << cnt << endl;
  }
  return 0;
}
