#include <cstdio>
#include <vector>
#include <algorithm>
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(!Same(es[i].from,es[i].to)) {
				bool a=false,b=false;
				for(int j=0;j<s;j++) {
					a|=Same(j,es[i].from);
					b|=Same(j,es[i].to);
				}
				if(a&&b) continue;
				Unite(es[i].from,es[i].to);
				sum+=es[i].cost;
			}
		}
		printf("%d\n",sum);
	}
}