#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;

const int MAX_E = 100000;
const int MAX_V = 1000;

struct edge{
	int u, v, cost;
	edge(int u_, int v_, int cost_ ){
		u = u_;
		v = v_;
		cost = cost_;
	} 
};

bool comp(const edge& e1, const edge& e2){
	return e1.cost < e2.cost;
}

// 入力
int s, d;
// 親
int par[MAX_V];
// 木の深さ
int rank[MAX_V];

// union-find の初期化
void init_union_find(int n){
	for(int i=0 ; i < n ; i++ ){
		par[i] = i;
		rank[i] = 0;
	}
}

// x の root を返す
int find(int x){
	if( par[x] == x ){
		return x;
	}else{
		return par[x] = find( par[x] );
	}
}

// x と y の属する集合を併合
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]++;
	}
}

// x と y が同じ集合に属するかどうかを返す
bool same(int x, int y){
	return find(x) == find(y);
}

// ノード x が地区かどうか
bool is_district(int x){
	return ( x >= s );
}

int solve(vector<edge> v){
	init_union_find( d + s );
	sort( v.begin() , v.end() , comp );
	int used[MAX_V] = {0};
	
	int sum = 0;
	bool flag = false;
	for(int i=0 ; i < v.size() ; i++ ){
		edge e = v[i];
		
		if( !same( e.u , e.v ) ){
			if( !is_district( e.u ) && used[e.v] == 0 ){
				unite( e.u , e.v );
				flag = true;
				sum += e.cost;
				used[e.v] = 1;
				for(int i = s ; i < s+d ; i++ ){
					if( same( e.v , i ) ){
						used[i] = 1;
					}
				}
			}else if( is_district( e.u ) && is_district( e.v ) ){ 
				unite( e.u , e.v );
				sum += e.cost;
				if( used[e.u] && !used[e.v] ){
					used[e.v] = 1;
					for(int i = s ; i < s+d ; i++ ){
						if( same( e.v , i ) ){
							used[i] = 1;
						}
					}
				}
				if( !used[e.u] && used[e.v] ){
					used[e.u] = 1;
					for(int i = s ; i < s+d ; i++ ){
						if( same( e.u , i ) ){
							used[i] = 1;
						}
					}
				}
			}
		}
		
		int cnt=0;
		for(int i = s ; i < s+d ; i++ ){
			cnt += used[i];
		}
		if( cnt == d && flag ){
			break;
		}
	}
	return sum;
}

int main(){
	
	while( cin >> s >> d , s || d ){
		vector<edge> v;		
		
		for(int i=0 ; i < s ; i++ ){
			for(int j=0 ; j < d ; j++ ){
				int cost;
				cin >> cost;
				if( cost == 0 ) continue;
				
				edge e( i , j+s , cost );
				v.push_back( e );
			}
		}
		for(int i=s ; i < d+s-1 ; i++ ){
			for(int j=i+1 ; j < d+s ; j++ ){
				int cost;
				cin >> cost;
				if( cost == 0 ) continue;
				
				edge e( i , j , cost );
				v.push_back( e );
			}
		}
		int ans = solve( v );
		cout << ans << endl;
	}
}