#include <cstdio>
#include <map>
#include <queue>
#include <cstring>
#include <vector>
using namespace std;

typedef pair<double, int> pii;
typedef long long ll;
int N, M;
double vec[101][101];
double dist[101][101];
bool seen[101];

typedef double Weight;
struct Edge {
  int src;
  int dest;
  Weight weight;
  Edge(int src, int dest, Weight weight) : src(src), dest(dest), weight(weight) {;}
  bool operator<(const Edge &rhs) const {
    if (weight != rhs.weight) { return weight > rhs.weight; }
    if (src != rhs.src) { return src < rhs.src; }
    return dest < rhs.dest;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void SccDfs(const Graph &g, int from, vector<int> &visit, vector<int> &st) {
  visit[from] = 1;
  for (Edges::const_iterator it = g[from].begin(); it != g[from].end(); it++) {
    if (visit[it->dest]) { continue; }
    SccDfs(g, it->dest, visit, st);
  }
  st.push_back(from);
}

vector<vector<int> > Scc(const Graph &g) {
  const int n = g.size();
  vector<vector<int> > ret;
  Graph revg(n);
  for (int i = 0; i < n; i++) {
    for (Edges::const_iterator it = g[i].begin(); it != g[i].end(); it++) {
      revg[it->dest].push_back(Edge(it->dest, i, it->weight));
    }
  }
  vector<int> st;
  vector<int> visit(n, 0);
  for (int i = 0; i < n; i++) {
    if (visit[i]) { continue; }
    SccDfs(g, i, visit, st);
  }
  visit = vector<int>(n, 0);
  for (int i = n - 1; i >= 0; i--) {
    int index = st[i];
    if (visit[index]) { continue; }
    vector<int> nret;
    SccDfs(revg, index, visit, nret);
    ret.push_back(nret);
  }
  return ret;
}

// select min weight edge
Graph SccGraph(const Graph &g) {
  vector<vector<int> > scc = Scc(g);
  const int n = g.size();
  const int m = scc.size();
  vector<int> mapto(n);
  for (int i = 0; i < (int)scc.size(); i++) {
    for (int j = 0; j < (int)scc[i].size(); j++) {
      mapto[scc[i][j]] = i;
    }
  }
  Graph ret(m);
  vector<int> indexs(m, -1);
  for (int from = 0; from < m; from++) {
    int e = 0;
    for (int i = 0; i < (int)scc[from].size(); i++) {
      for (Edges::const_iterator it = g[scc[from][i]].begin(); it != g[scc[from][i]].end(); it++) {
        int to = mapto[it->dest];
        if (from == to) { continue; } // loopback
        if (indexs[to] == -1) {
          ret[from].push_back(Edge(from, to, it->weight));
          indexs[to] = e++;
        } else {
          // select edge
          ret[from][indexs[to]].weight = min(ret[from][indexs[to]].weight, it->weight);
        }
      }
    }
    for (Edges::const_iterator it = ret[from].begin(); it != ret[from].end(); it++) {
      indexs[it->dest] = -1;
    }
  }
  return ret;
}

Weight Arborescence(const Graph &g, int root) {
  const int n = g.size();
  Weight ret = 0;
  vector<Weight> inCost(n, 1e9);
  vector<int> parent(n, -1);
  for (int from = 0; from < n; from++) {
    for (Edges::const_iterator it = g[from].begin(); it != g[from].end(); it++) {
      if (it->dest == from) { continue; }
      if (it->weight < inCost[it->dest]) {
        parent[it->dest] = from;
        inCost[it->dest] = it->weight;
      }
      inCost[it->dest] = min(inCost[it->dest], it->weight);
    }
  }
  Graph ng(n);
  for (int i = 0; i < n; i++) {
    if (i == root) { continue; }
    if (parent[i] == -1) { return 1e9; }
    ng[parent[i]].push_back(Edge(parent[i], i, 0));
    ret += inCost[i];
  }
  vector<vector<int> > connect = Scc(ng);
  int m = connect.size();
  if (m == n) { return ret; }
  vector<int> mapto(n, -1);
  vector<int> cycle(n, 0);
  ret = 0;
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < (int)connect[i].size(); j++) {
      mapto[connect[i][j]] = i;
      if (connect[i].size() != 1) {
        cycle[connect[i][j]] = 1;
        ret += inCost[connect[i][j]];
      }
    }
  }
  ng = Graph(m);
  for (int from = 0; from < n; from++) {
    for (Edges::const_iterator it = g[from].begin(); it != g[from].end(); it++) {
      int to = it->dest;
      if (to == root || mapto[from] == mapto[to]) { continue; }
      Weight cost = it->weight;
      if (cycle[to]) {
        cost -= inCost[to];
      }
      ng[mapto[from]].push_back(Edge(mapto[from], mapto[to], cost));
    }
  }
  return min(1e9, (double)ret + Arborescence(ng, mapto[root]));
}

// p - r * q
double ternary_search(int p, int q) {
    double lo = -(1e9), hi = 1e9;
    for (int i=0; i<100; ++i) {
        double m1 = (2*lo + hi)/3, m2 = (lo + 2*hi)/3;
        double n1 = 0.0, n2 = 0.0;
        for (int j=0; j<N; ++j) {
            n1 += (vec[p][j] - m1 * vec[q][j]) * (vec[p][j] - m1 * vec[q][j]);
            n2 += (vec[p][j] - m2 * vec[q][j]) * (vec[p][j] - m2 * vec[q][j]);
        }
        if (n1 > n2) lo = m1;
        else hi = m2;
    }
    double ret = 0;
    for (int i=0; i<N; ++i)
        ret += (vec[p][i] - lo * vec[q][i]) * (vec[p][i] - lo * vec[q][i]);
    return ret;
}

int main() {
    scanf("%d %d", &N, &M);
    for (int i=0; i<M; ++i)
        for (int j=0; j<N; ++j)
            scanf("%lf", &vec[i][j]);
    for (int j=0; j<N; ++j)
        vec[M][j] = 0.0;
    M++;

    Graph g(M);
    vector<pair<double, pair<int,int> > > e;
    for (int i=0; i<M; ++i)
        for (int j=0; j<M; ++j) {
            if (i == j) continue;
            g[j].push_back(Edge(j, i, ternary_search(i, j)));
            //dist[j][i] = ternary_search(i, j);
        }

    printf("%.20f\n", Arborescence(g, M-1));
}

Measured memory_bytes: 7804