#include <bits/stdc++.h>
using namespace std;
template <class T>
T gcd(T a, T b) {
  if (!b) return a;
  return gcd(b, a % b);
}
template <class T>
T power(T a, T b) {
  T res(1);
  while (b) {
    if (b & 1) res = res * a;
    a = a * a;
    b >>= 1;
  }
  return res;
}
template <class T>
T powerM(T a, T b, T mod) {
  T res(1);
  while (b) {
    if (b & 1) res = res * a % mod;
    a = a * a % mod;
    b >>= 1;
  }
  return res;
}
const int infi = 2147483647;
const long long infl = 9223372036854775807;
typedef bool BB[64];
struct Maxclique {
  const BB *e;
  int pk, level;
  const float Tlimit;
  struct Vertex {
    int i, d;
    Vertex(int i) : i(i), d(0) {}
  };
  vector<Vertex> V;
  vector<vector<int> > C;
  vector<int> QMAX, Q;
  static bool desc_degree(const Vertex &vi, const Vertex &vj) {
    return vi.d > vj.d;
  }
  void init_colors(vector<Vertex> &v) {
    const int max_degree = v[0].d;
    for (int i = 0; i < (int)v.size(); i++) v[i].d = min(i, max_degree) + 1;
  }
  void set_degrees(vector<Vertex> &v) {
    for (int i = 0, j; i < (int)v.size(); i++)
      for (v[i].d = j = 0; j < int(v.size()); j++) v[i].d += e[v[i].i][v[j].i];
  }
  struct StepCount {
    int i1, i2;
    StepCount() : i1(0), i2(0) {}
  };
  vector<StepCount> S;
  bool cut1(const int pi, const vector<int> &A) {
    for (int i = 0; i < (int)A.size(); i++)
      if (e[pi][A[i]]) return true;
    return false;
  }
  void cut2(const vector<Vertex> &A, vector<Vertex> &B) {
    for (int i = 0; i < (int)A.size() - 1; i++)
      if (e[A.back().i][A[i].i]) B.push_back(A[i].i);
  }
  void color_sort(vector<Vertex> &R) {
    int j = 0, maxno = 1, min_k = max((int)QMAX.size() - (int)Q.size() + 1, 1);
    C[1].clear(), C[2].clear();
    for (int i = 0; i < (int)R.size(); i++) {
      int pi = R[i].i, k = 1;
      while (cut1(pi, C[k])) k++;
      if (k > maxno) maxno = k, C[maxno + 1].clear();
      C[k].push_back(pi);
      if (k < min_k) R[j++].i = pi;
    }
    if (j > 0) R[j - 1].d = 0;
    for (int k = min_k; k <= maxno; k++)
      for (int i = 0; i < (int)C[k].size(); i++) R[j].i = C[k][i], R[j++].d = k;
  }
  void expand_dyn(vector<Vertex> &R) {
    S[level].i1 = S[level].i1 + S[level - 1].i1 - S[level].i2;
    S[level].i2 = S[level - 1].i1;
    while ((int)R.size()) {
      if ((int)Q.size() + R.back().d > (int)QMAX.size()) {
        Q.push_back(R.back().i);
        vector<Vertex> Rp;
        cut2(R, Rp);
        if ((int)Rp.size()) {
          if ((float)S[level].i1 / ++pk < Tlimit) degree_sort(Rp);
          color_sort(Rp);
          S[level].i1++, level++;
          expand_dyn(Rp);
          level--;
        } else if ((int)Q.size() > (int)QMAX.size())
          QMAX = Q;
        Q.pop_back();
      } else
        return;
      R.pop_back();
    }
  }
  void mcqdyn(int *maxclique, int &sz) {
    set_degrees(V);
    sort(V.begin(), V.end(), desc_degree);
    init_colors(V);
    for (int i = 0; i < (int)V.size() + 1; i++) S[i].i1 = S[i].i2 = 0;
    expand_dyn(V);
    sz = (int)QMAX.size();
    for (int i = 0; i < (int)QMAX.size(); i++) maxclique[i] = QMAX[i];
  }
  void degree_sort(vector<Vertex> &R) {
    set_degrees(R);
    sort(R.begin(), R.end(), desc_degree);
  }
  Maxclique(const BB *conn, const int sz, const float tt = 0.025)
      : pk(0), level(1), Tlimit(tt) {
    for (int i = 0; i < sz; i++) V.push_back(Vertex(i));
    e = conn, C.resize(sz + 1), S.resize(sz + 1);
  }
};
int n, m, k, T;
bool a[64][64];
int res[64];
int main() {
  scanf("%d", &n), scanf("%d", &k);
  for (int i = 0; i < (n); ++i)
    for (int j = 0; j < (n); ++j) scanf("%d", &a[i][j]);
  m = 0;
  Maxclique(a, n).mcqdyn(res, m);
  double ans = 1.0 * k * k / (m * m) * m * (m - 1) / 2;
  printf("%.10lf\n", ans);
  return 0;
}
