#include<iostream>
#include<algorithm>
#include<vector>
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<28)
#define MAX 10000
#define all(n) (n).begin(),(n).end()
using namespace std;
struct Pox
{
  int from,to,cost;
  Pox(int from=-1,int to=-1,int cost=-1):from(from),to(to),cost(cost){}
  bool operator < (const Pox &a)const
  {
    return cost < a.cost;
  }
};

int n,m;
int par[MAX+1];

void init()
{
  rep(i,MAX)par[i] = i;
}

int find(int x)
{
  if(x == par[x])return x;
  return par[x] = find(par[x]);
}

void unit(int x,int y)
{
  x = find(x);
  y = find(y);
  if(x != y)par[x] = y;
}

bool same(int x,int y)
{
  return find(x) == find(y);
}

int kruskal(vector<Pox> &G)
{
  sort(all(G));
  init();
  int res = 0;
  int gsize = G.size();
  rep(i,gsize)
    {
      Pox pox = G[i];
      if(!same(pox.from,pox.to))
	{
	  unit(pox.from,pox.to);
	  res += pox.cost;
	}
    }
  return res;
}

int main()
{
  while(cin >> n >> m,n|m)
    {
      vector<Pox> G;
      int cost;
      rep(i,n)
	{
	  //cout << "from " << i << " : " << endl;
	  REP(j,n,n+m)
	    {
	      cin >> cost;
	      if(cost == 0)cost = inf;
	      //cout << 0 << " to " << j << " : " << cost << endl;
	      G.push_back(Pox(0,j,cost));
	    }
	  //cout << endl;
	}     
      
      REP(i,n,n+m-1)
	{
	  //cout << "from " << i << " : " << endl;
	  REP(j,i+1,n+m)
	    {
	      cin >> cost;
	      if(cost == 0)cost = inf;
	      //cout << i << " to " << j << " : " << cost << endl;
	      G.push_back(Pox(i,j,cost));
	    }
	  //cout << endl;
	}
      cout << kruskal(G) << endl;
    }
  return 0;
}