#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <map>
#include <algorithm>

#define REP(i,n) for(int i=0;i<(int)(n);i++)

using namespace std;

typedef int Weight;
struct Edge{
  int src, dest; Weight weight;
  bool operator < (const Edge &rhs) const {return weight > rhs.weight;}
};

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

Edges prim(Graph &g){
  Edges res;
  vector<int> visited(g.size(), 0);
  priority_queue<Edge> q;
  q.push((Edge){-1, 0, 0});
  while (!q.empty()) {
    Edge e = q.top();
    q.pop();
    if (visited[e.dest]) continue;
    if (e.src >= 0) res.push_back(e);
    visited[e.dest] = 1;
    for (Edge i : g[e.dest]) if(visited[i.dest] == 0) q.push(i);
  }
  sort(res.rbegin(), res.rend());
  return res;
}

int main() {
  while(1){
    int s,d;
    cin>>s>>d;
    if(!s)break;
    Graph g(s+d+1);
    REP(i,s){
      REP(j,d){
        int l;
        cin>>l;
        if (l>0) {
          g[i+d].push_back({i+d,j,l});
          g[j].push_back({j,i+d,l});
        }
      }
    }
    REP(i,d-1) {
      REP(j,d-i-1) {
        int l;
        cin>>l;
        if (l>0) {
          g[i].push_back({i,i+j+1,l});
          g[i+j+1].push_back({i+j+1,i,l});
        }
      }
    }
    REP(i,s){
      g[s+d].push_back({s+d,i+d,0});
      g[i+d].push_back({i+d,s+d,0});
    }
    auto res = prim(g);
    int sum = 0;
    for (Edge e : res) sum += e.weight;
    cout<<sum<<endl;
  }
  return 0;
}