#include<iostream>
#include<queue>

using namespace std;

#define REP(i,a,e) for(int i = (a); i < (e); ++i)
#define MAX 101
#define INFTY 1000
#define NIL (-1)

bool visited[MAX];
int cost[MAX];
int G[MAX][MAX];
int W[MAX][MAX];

int MSTPrim(int nodes, int st){
	int ret = 0;

	for(int i = 0; i < nodes; ++i){
		visited[i] = false;
		cost[i] = INFTY;
	}

	cost[0] = 0;

	while( true ){
		int mincost = INFTY;
		int nmin = 0;

		/* EXTRACT-MIN() */
		for(int i = 0; i < nodes; ++i){
			if( !visited[i] && mincost > cost[i] ){
				mincost = cost[i];
				nmin = i;
			}
		}

		/* cannot extract */
		if( mincost == INFTY )
			break;

		visited[nmin] = true;

		for(int i = 0; i < nodes; ++i){
			/* not-connected */
			if( visited[i] || W[nmin][i] == INFTY )
				continue;

			if( W[nmin][i] < cost[i] ){
				cost[i] = W[nmin][i];
			}
		}
	}
	for(int i = 0; i < nodes; ++i){
		ret += cost[i];
	}

	return ret;
}

void ResetGraph(){
	REP(i,0,MAX)REP(j,0,MAX){
		W[i][j] = INFTY;
	}
}

int main(){
	while(true){
		int s, d;

		ResetGraph();

		scanf("%d%d", &s, &d);
		if( s == 0 && d == 0 )
			break;

		REP(i,0,s){
			REP(j,0,d){
				int w;
				scanf("%d", &w);
				W[i][s+j] = W[s+j][i] = w == 0 ? INFTY : w;
			}
			REP(j,0,s){
				W[i][j] = W[j][i] = 0;
			}
		}

		REP(i,0,d-1){
			REP(j,1,d-i){
				int w;
				scanf("%d", &w);
				W[i+s][i+j+s] = W[i+j+s][i+s] = w == 0 ? INFTY : w;
			}
		}

		cout << MSTPrim( s+d, 0 ) << endl;
	}
	return 0;
}