#include<queue>
#include<cstdio>
#include<vector>
#include<functional>

#define	mp	make_pair
#define	pb	push_back

using namespace std;

typedef	vector<bool>	vb;
typedef	pair<int,int>	pii;
typedef	vector<pii>		vpii;

struct Edge{
	int cost,u,v;
	Edge(int _cost,int _u,int _v):cost(_cost),u(_u),v(_v){}
	bool operator>(const Edge &e)const{return cost>e.cost;}
};

int main(){
	for(int m,n;scanf("%d%d",&m,&n),m||n;){
		vector<vpii> adj(m+n+1);	// <cost,destination>
		for(int i=0;i<m;i++)for(int j=m;j<m+n;j++){
			int a;	scanf("%d",&a);
			if(a!=0){
				adj[i].pb(mp(a,j));
				adj[j].pb(mp(a,j));
			}
		}
		for(int i=m;i<m+n;i++)for(int j=i+1;j<m+n;j++){
			int a;	scanf("%d",&a);
			if(a!=0){
				adj[i].pb(mp(a,j));
				adj[j].pb(mp(a,i));
			}
		}
		int super=m+n;
		for(int i=0;i<m;i++){
			adj[super].pb(mp(0,i));
			adj[i].pb(mp(0,super));
		}

		vb visited(m+n+1);
		priority_queue< Edge,vector<Edge>,greater<Edge> > pq;
		pq.push(Edge(0,-1,super));	// vertual edge
		int total=0;
		while(!pq.empty()){
			Edge a=pq.top();	pq.pop();
			int cost=a.cost,v=a.v;
			if(visited[v])	continue;
			visited[v]=true;
			total+=cost;
			for(int i=0;i<adj[v].size();i++){
				int nextcost=adj[v][i].first;
				int nextnode=adj[v][i].second;
				if(!visited[nextnode])	pq.push(Edge(nextcost,v,nextnode));
			}
		}

		printf("%d\n",total);
	}

	return 0;
}