#include <bits/stdc++.h>
using namespace std;
int Par[100], Rank[100];
void Init(int n) {
  for (int i = 0; i < n; i++) {
    Par[i] = i;
    Rank[i] = 0;
  }
}
int Find(int x) {
  if (Par[x] == x) {
    return x;
  } else {
    return Par[x] = Find(Par[x]);
  }
}
void Unite(int x, int y) {
  x = Find(x);
  y = Find(y);
  if (x == y) return;
  if (Rank[x] < Rank[y]) {
    Par[x] = y;
  } else {
    Par[y] = x;
    if (Rank[x] == Rank[y]) Rank[x]++;
  }
}
bool Same(int x, int y) { return Find(x) == Find(y); }
struct Edge {
  int from, to, cost;
  Edge(int _f, int _t, int _c) { from = _f, to = _t, cost = _c; }
  bool operator<(const Edge& E) const { return cost < E.cost; }
};
int main() {
  int s, d;
  while (scanf("%d %d", &s, &d), s) {
    vector<Edge> es;
    for (int i = 0; i < s; i++) {
      for (int j = 0; j < d; j++) {
        int cost;
        scanf("%d", &cost);
        if (cost != 0) es.push_back(Edge(i, j + 50, cost));
      }
    }
    for (int i = 0; i < (d - 1); i++) {
      for (int j = 0; j < (d - i - 1); j++) {
        int cost;
        scanf("%d", &cost);
        if (cost != 0) es.push_back(Edge(i + 50, i + (j + 1) + 50, cost));
      }
    }
    sort(es.begin(), es.end());
    Init(100);
    int sum = 0;
    for (int i = 0; i < es.size(); i++) {
      if (es[i].from >= 6) {
        bool same = false;
        for (int i = 0; i < s; i++) {
          if (Same(i, es[i].from)) same = true;
        }
        if (same) continue;
      }
      if (es[i].to >= 6) {
        bool same = false;
        for (int i = 0; i < s; i++) {
          if (Same(i, es[i].to)) same = true;
        }
        if (same) continue;
      }
      if (!Same(es[i].from, es[i].to)) {
        Unite(es[i].from, es[i].to);
        sum += es[i].cost;
      }
    }
    printf("%d\n", sum);
  }
}
