#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1);
const double EPS = 1e-8;
const int inf = 1e8;
struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) {}
  bool unionSet(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y) return 0;
    if (data[y] < data[x]) swap(x, y);
    data[x] += data[y], data[y] = x;
    return 1;
  }
  bool findSet(int x, int y) { return root(x) == root(y); }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  int size(int x) { return -data[root(x)]; }
};
class KRK {
 public:
  struct edge {
    int from, to, cost;
  };
  vector<edge> G;
  int n, m;
  KRK(int size1, int size2) {
    n = size1;
    m = size2;
  }
  void add_edge(int a, int b, int c) {
    edge e = {a, b, c};
    G.push_back(e);
  }
  int krk() {
    int sum = 0;
    sort(G.begin(), G.end(), [](edge a, edge b) { return a.cost < b.cost; });
    UnionFind uf(n + m);
    for (int i = 0; i < G.size(); i++) {
      edge e = G[i];
      bool h1 = false, h2 = false;
      for (int j = 0; j < n; j++) {
        if (uf.findSet(e.from, m + j)) h1 = true;
        if (uf.findSet(e.to, m + j)) h2 = true;
      }
      if (h1 + h2 != 2 && !uf.findSet(e.from, e.to)) {
        sum += e.cost;
        uf.unionSet(e.from, e.to);
      }
    }
    return sum;
  }
};
int main() {
  int n, m;
  while (cin >> n >> m) {
    KRK krk(n, m);
    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++) {
        int a;
        cin >> a;
        if (a) krk.add_edge(j, m + i, a);
      }
    for (int i = 0; i < m - 1; i++)
      for (int j = 0; j < m - i - 1; j++) {
        int a;
        cin >> a;
        if (a) krk.add_edge(i, i + j + 1, a);
      }
    cout << krk.krk() << endl;
  }
}
