#include <bits/stdc++.h>
using namespace std;
int n1, n2;
struct Kruskal {
  struct UnionFind {
    int n;
    vector<int> r, p;
    UnionFind() {}
    UnionFind(int sz) : n(sz), r(sz, 1), p(sz, 0) {
      iota(p.begin(), p.end(), 0);
    }
    int find(int x) { return (x == p[x] ? x : p[x] = find(p[x])); }
    bool same(int x, int y) { return find(x) == find(y); }
    void unite(int x, int y) {
      x = find(x);
      y = find(y);
      if (x == y) return;
      if (r[x] < r[y]) swap(x, y);
      r[x] += r[y];
      p[y] = x;
    }
  };
  struct edge {
    int from, to, cost, used;
    edge() {}
    edge(int from, int to, int cost)
        : from(from), to(to), cost(cost), used(0) {}
    bool operator<(const edge& e) const { return cost < e.cost; }
  };
  int n;
  vector<edge> edges;
  Kruskal() {}
  Kruskal(int sz) : n(sz) {}
  void add_edge(int u, int v, int c) { edges.emplace_back(u, v, c); }
  void input(int m, int offset = 0) {
    int a, b, c;
    for (int i = 0; i < m; i++) {
      cin >> a >> b >> c;
      add_edge(a + offset, b + offset, c);
    }
  }
  int build() {
    sort(edges.begin(), edges.end());
    UnionFind uf(n + 1);
    int res = 0;
    for (auto& e : edges) {
      if (!uf.same(e.from, e.to)) {
        int f1 = 0, f2 = 0;
        for (int i = 0; i < n1; i++)
          if (uf.same(e.from, i)) f1++;
        for (int i = 0; i < n1; i++)
          if (uf.same(e.to, i)) f2++;
        if (!f1 || !f2) res += e.cost;
        uf.unite(e.from, e.to);
        e.used = 1;
      }
    }
    return res;
  }
};
int main() {
  while (cin >> n1 >> n2, n1) {
    Kruskal K(n1 + n2);
    for (int i = 0; i < n1; i++) {
      for (int j = 0; j < n2; j++) {
        int x;
        cin >> x;
        if (x) K.add_edge(i, j + n1, x);
      }
    }
    for (int i = 0; i < n2; i++) {
      for (int j = i + 1; j < n2; j++) {
        int x;
        cin >> x;
        if (x) K.add_edge(i + n1, j + n1, x);
      }
    }
    cout << K.build() << endl;
  }
}
