#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;i++)
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;
        rep(i,n1)if(uf.same(e.from,i))f1++;
        rep(i,n1)if(uf.same(e.to,i))f2++;
        if(!f1||!f2)res+=e.cost;
        uf.unite(e.from,e.to);
      }
    }
    return res;
  }
};
int main(){
  while(cin>>n1>>n2,n1){
    Kruskal K(n1+n2);
    rep(i,n1){
      rep(j,n2){
        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;
  }
}
