#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <cstdlib>

using namespace std;

#define pb push_back
#define mp make_pair
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define REP(i,j,k) for(int i=j;i<(int)(k);++i)
#define foreach(i,c) for(__typeof(c.begin()) i=c.begin();i!=c.end();++i)
#define all(x) (x).begin(),(x).end()
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef long long ll;
const int INF = 99999999;
const double EPS = 1e-9;

struct UnionFind
{
    vi par,rank;
    UnionFind(int n){
        par.resize(n),rank.resize(n,0);
        rep(i,n) par[i]=i;
    }

    int find(int x){
        return par[x]==x ? x : 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 s,d,c;
    Edge(int s, int d, int c) : s(s),d(d),c(c){}
    bool operator<(const Edge &x) const{
        return c < x.c;
    }
};

int s,d,in;

int main()
{
    while(cin>>s>>d,s&&d){
        vector<Edge> ve;
        rep(i,s)rep(j,d){
            cin >> in;
            ve.pb(Edge(i,j+s,in));
        }
        rep(i,d-1)REP(j,i+1,d){
            cin >> in;
            ve.pb(Edge(i+s,j+s,in));
        }

        UnionFind uf(s+d);
        sort(all(ve));
        REP(i,1,s) uf.unite(0,i);

//        rep(i,ve.size()) cout << ve[i].c << endl;
        int ans = 0;
        rep(i,ve.size()){
            if(!ve[i].c) continue;
            if(uf.same(ve[i].s,ve[i].d)) continue;
            ans+=ve[i].c;
            uf.unite(ve[i].s,ve[i].d);
            }
        cout << ans << endl;
    }

    return 0;
}