#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> P;

#define EACH(i,a) for (auto& i : a)
#define FOR(i,a,b) for (ll i=(a);i<(b);i++)
#define RFOR(i,a,b) for (ll i=(b)-1;i>=(a);i--)
#define REP(i,n) for (ll i=0;i<(n);i++)
#define RREP(i,n) for (ll i=(n)-1;i>=0;i--)
#define debug(x) cout<<#x<<": "<<x<<endl
#define pb push_back
#define ALL(a) (a).begin(),(a).end()

const ll linf = 1e18;
const int inf = 1e9;
const double eps = 1e-12;
const double pi = acos(-1);

template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
    EACH(x,vec) is >> x;
    return is;
}
template<typename T>
ostream& operator<<(ostream& os, vector<T>& vec) {
    REP(i,vec.size()) {
        if (i) os << " ";
        os << vec[i];
    }
    return os;
}
template<typename T>
ostream& operator<<(ostream& os, vector< vector<T> >& vec) {
    REP(i,vec.size()) {
        if (i) os << endl;
        os << vec[i];
    }
    return os;
}

typedef double Weight;
struct Edge {
  int src, dst;
  Weight w;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), w(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.w != f.w ? e.w > f.w : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;


void backward_traverse(int v, int s, int r,
  Graph &gg,
  vector<int> &no, vector< vector<int> > &comp,
  vector<int> &prev, vector< vector<int> > &next, vector<Weight> &mcost,
  vector<int> &mark, Weight &cost, bool &found) {
  const int n = gg.size();
  if (mark[v]) {
    vector<int> temp = no;
    found = true;
    do {
      cost += mcost[v];
      v = prev[v];
      if (v != s) {
        while (comp[v].size() > 0) {
          no[comp[v].back()] = s;
          comp[s].push_back(comp[v].back());
          comp[v].pop_back();
        }
      }
    } while (v != s);

    for (int k = 0; k < comp[s].size(); ++k) {
      int j = comp[s][k];
      if (j != r)
        for (int l = 0; l < gg[j].size(); ++l)
          if (no[ gg[j][l].src ] != s)
            gg[j][l].w -= mcost[ temp[j] ];
    }
  }
  mark[v] = true;
  for (int k = 0; k < next[v].size(); ++k) {
    int i = next[v][k];
    if (no[i] != no[v] && prev[ no[i] ] == v)
      if (!mark[ no[i] ] || i == s)
        backward_traverse(i, s, r, gg,
            no, comp, prev, next, mcost, mark, cost, found);
  }
}
Weight minimum_spanning_arborescence(int r, Graph &g) {
  const int n = g.size();
  Graph gg(n);
  for (int i = 0; i < g.size(); ++i)
    for (int j = 0; j < g[i].size(); ++j)
      gg[ g[i][j].dst ].push_back( g[i][j] );

  vector<int> no(n);
  vector< vector<int> > comp(n);
  for (int i = 0; i < n; ++i) {
    no[i] = i;
    comp[i].push_back(i);
  }
  Weight cost = 0;
  while (1) {
    vector<int> prev(n, -1);
    vector<Weight> mcost(n, inf);

    for (int j = 0; j < n; ++j) {
      if (j == r) continue;
      for (int k = 0; k < gg[j].size(); ++k) {
        int i = gg[j][k].src;
        if (no[i] != no[j]) {
          if (gg[j][k].w < mcost[ no[j] ]) {
            mcost[ no[j] ] = gg[j][k].w;
            prev[ no[j] ] = no[i];
          }
        }
      }
    }
    vector< vector<int> > next(n);
    for (int i = 0; i < n; ++i)
      if (prev[i] >= 0)
        next[ prev[i] ].push_back( i );

    bool stop = true;
    vector<int> mark(n);
    for (int i = 0; i < n; ++i) {
      if (i == r || mark[i] || comp[i].size() == 0) continue;
      bool found = false;
      backward_traverse(i, i, r, gg,
          no, comp, prev, next, mcost, mark, cost, found);
      if (found) stop = false;
    }
    if (stop) {
      for (int i = 0; i < n; ++i)
        if (prev[i] >= 0)
          cost += mcost[i];
      return cost;
    }
  }
}

double f(const vector<double>& v) {
    double res = 0;
    REP(i, v.size()) res += v[i]*v[i];
    return res;
}

vector<double> sub(const vector<double>& a, const vector<double>& b) {
    vector<double> res(a.size());
    REP(i, a.size()) res[i] = a[i] - b[i];
    return res;
}
vector<double> mul(const vector<double>& v, const double r) {
    vector<double> res(v.size());
    REP(i, v.size()) {
        res[i] = v[i]*r;
    }
    return res;
}

// |b - a * hoge|^2 -> min
double getW(const vector<double>& a, const vector<double>& b) {
    double l = -inf, r = inf;
    REP(t, 100) {
        double m1 = (2*l+r)/3, m2 = (l+2*r)/3;
        if ( f( sub(b, mul(a, m1)) ) < f( sub(b, mul(a, m2)) ) ) {
            r = m2;
        }
        else {
            l = m1;
        }
    }
    return f( sub(b, mul(a, (l + r)/2)) );
}
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    int n, m; cin >> n >> m;
    vector< vector<double> > v(m, vector<double>(n)); cin >> v;
    int s = m;
    Graph G(s+1);
    REP(i, m) REP(j, m) {
        G[i].pb( Edge(i, j, getW(v[i], v[j])) );
    }
    REP(i, m) {
        G[s].pb( Edge(s, i, f(v[i])) );
    }
    cout << fixed << setprecision(10);
    cout << minimum_spanning_arborescence(s, G) << endl;
}

Measured memory_bytes: 3508