#include <bits/stdc++.h>
using namespace std;
template <typename T>
bool chmax(T &m, const T &v) {
  if (v > m) return m = v, true;
  return false;
}
template <typename T>
bool chmin(T &m, const T &v) {
  if (v < m) return m = v, true;
  return false;
}
static const int HMAX32 = INT32_MAX / 2;
static const int HMIN32 = -HMAX32;
static const int64_t HMAX64 = INT64_MAX / 2;
static const int64_t HMIN64 = -HMAX64;
void fast_io() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
}
template <typename T>
struct ring_traits {
  static T zero() { return T(); }
  static T negate(const T &p) { return -p; }
  static T plus(const T &p1, const T &p2) { return p1 + p2; }
  static T minus(const T &p1, const T &p2) { return p1 - p2; }
  static T one() { return 1; }
  static T time(const T &p1, const T &p2) { return p1 * p2; }
  static void plus_assign(T &p1, const T &p2) { p1 += p2; }
  static void minus_assign(T &p1, const T &p2) { p1 -= p2; }
  static void time_assign(T &p1, const T &p2) { p1 *= p2; }
  static T inverse(const T &p) { return 1 / p; }
  static T divide(const T &p1, const T &p2) { return p1 / p2; }
  static void divide_assign(T &p1, const T &p2) { p1 /= p2; }
  static double norm(const T &p) { return std::abs(p); }
};
template <typename T, template <typename> class Ring = ring_traits>
struct matrix {
 private:
  std::vector<std::vector<T>> data;
  static Ring<T> traits;

 public:
  matrix() = default;
  matrix(int r, int c) : data(r, std::vector<T>(c, traits.zero())) {}
  static matrix scalar(int r, const T &val) {
    matrix ret(r, r);
    for (int i = 0; i < r; ++i) ret.data[i][i] = val;
    return ret;
  }
  static matrix eye(int r) { return scalar(r, traits.one()); }
  static matrix diagonal(const std::vector<T> &diag) {
    int r = (int)diag.size();
    matrix ret(r, r);
    for (int i = 0; i < r; ++i) ret.data[i][i] = diag[i];
    return ret;
  }
  void swap(matrix &that) { std::swap(data, that.data); }
  int r() const { return (int)data.size(); }
  int c() const {
    if (data.size()) return (int)data[0].size();
    return 0;
  }
  const std::vector<T> &operator[](int m) const { return data[m]; }
  std::vector<T> &operator[](int m) { return data[m]; }
  bool operator==(const matrix &that) const { return data == that.data; }
  std::vector<T> column(int n) {
    std::vector<T> ret;
    ret.reserve(r());
    for (auto &row : data) ret.push_back(row[n]);
  }
  void resize(int new_m, int new_n) {
    T zero = traits.zero();
    data.resize(new_m);
    for (auto &row : data) row.resize(new_n);
  }
  matrix &negate() {
    for (auto &row : data)
      for (T &ele : row) ele = traits.negate(ele);
    return *this;
  }
  matrix operator-() const { return matrix(*this).negate(); }
  matrix &operator+=(const T &scalar) {
    for (auto &row : data)
      for (T &ele : row) traits.plus_assign(ele, scalar);
    return *this;
  }
  matrix &operator+(const T &scalar) const {
    matrix ret(*this);
    return ret += scalar;
  }
  matrix &operator-=(const T &scalar) {
    for (auto &row : data)
      for (T &ele : row) traits.minus_assign(ele, scalar);
    return *this;
  }
  matrix &operator-(const T &scalar) const {
    matrix ret(*this);
    return ret -= scalar;
  }
  matrix &operator*=(const T &scalar) {
    for (auto &row : data)
      for (T &ele : row) traits.time_assign(ele, scalar);
    return *this;
  }
  matrix &operator*(const T &scalar) const {
    matrix ret(*this);
    return ret *= scalar;
  }
  matrix &operator/=(const T &scalar) {
    for (auto &row : data)
      for (T &ele : row) traits.divide_assign(ele, scalar);
    return *this;
  }
  matrix &operator/(const T &scalar) const {
    matrix ret(*this);
    return ret /= scalar;
  }
  matrix &operator+=(const matrix &that) {
    int rr = r(), cc = c();
    if (rr != that.r() || cc != that.c()) throw 0;
    for (int i = 0; i < rr; ++i) {
      for (int j = 0; j < cc; ++j) {
        traits.plus_assign(data[i][j], that.data[i][j]);
      }
    }
    return *this;
  }
  matrix &operator+(const matrix &that) const {
    matrix ret(*this);
    return ret += that;
  }
  matrix &operator-=(const matrix &that) {
    int rr = r(), cc = c();
    if (rr != that.r() || cc != that.c()) throw 0;
    for (int i = 0; i < rr; ++i) {
      for (int j = 0; j < cc; ++j) {
        traits.minus_assign(data[i][j], that.data[i][j]);
      }
    }
    return *this;
  }
  matrix &operator-(const matrix &that) const {
    matrix ret(*this);
    return ret -= that;
  }
  matrix operator*(const matrix &that) const {
    int mm = r(), nn = c(), pp = that.c();
    const matrix &self = *this;
    if (nn != that.r()) throw 0;
    matrix ret(mm, pp);
    for (int i = 0; i < mm; ++i) {
      for (int j = 0; j < pp; ++j) {
        T acc = traits.zero();
        for (int k = 0; k < nn; ++k)
          traits.plus_assign(acc,
                             traits.time(self.data[i][k], that.data[k][j]));
        ret.data[i][j] = acc;
      }
    }
    return ret;
  }
  matrix &operator*=(const matrix &that) { return *this = *this * that; }
};
template <typename T, template <typename> class Ring>
matrix<T, Ring> operator+(const T &value, const matrix<T, Ring> &p1) {
  matrix<T, Ring> ret(p1);
  return ret += value;
}
template <typename T, template <typename> class Ring>
matrix<T, Ring> operator*(const T &value, const matrix<T, Ring> &p1) {
  matrix<T, Ring> ret(p1);
  return ret *= value;
}
template <typename T, template <typename> class Ring>
matrix<T, Ring> operator-(const T &value, const matrix<T, Ring> &p1) {
  matrix<T, Ring> ret(p1);
  return ret.negate() += value;
}
template <typename T, template <typename> class Ring>
void swap(matrix<T, Ring> &p1, matrix<T, Ring> &p2) {
  p1.swap(p2);
}
template <typename T, template <typename> class Ring = ring_traits>
matrix<T, Ring> permutation_matrix(const std::vector<int> &p) {
  int n = (int)p.size();
  Ring<T> traits;
  matrix<T, Ring> P(n, n);
  for (int i = 0; i < n; ++i) P[i][p[i]] = traits.one();
  return P;
}
template <typename T, template <typename> class Ring>
int LU_decompose(const matrix<T, Ring> &A, matrix<T, Ring> &L,
                 matrix<T, Ring> &U) {
  int n = A.r();
  Ring<T> traits;
  if (n != A.c()) throw 0;
  L = matrix<T, Ring>::eye(n);
  U = A;
  for (int j = 0; j < n; ++j) {
    if (U[j][j] == traits.zero()) return -1;
    for (int i = j + 1; i < n; ++i) {
      T lij = traits.divide(U[i][j], U[j][j]);
      L[i][j] = lij;
      U[i][j] = 0;
      for (int k = j + 1; k < n; ++k)
        traits.minus_assign(U[i][k], U[j][k] * lij);
    }
  }
  return 0;
}
template <typename T, template <typename> class Ring>
int PLU_decompose(const matrix<T, Ring> &A, std::vector<int> &p,
                  matrix<T, Ring> &L, matrix<T, Ring> &U, bool &positive) {
  int n = A.r();
  Ring<T> traits;
  if (n != A.c()) throw 0;
  positive = true;
  U = A;
  L = matrix<T, Ring>(n, n);
  p = std::vector<int>(n);
  for (int i = 0; i < n; ++i) p[i] = i;
  for (int j = 0; j < n; ++j) {
    double max_norm = traits.norm(U[j][j]);
    int max_index = j;
    for (int jj = j + 1; jj < n; ++jj) {
      double cur_norm = traits.norm(U[jj][j]);
      if (cur_norm > max_norm) {
        max_norm = cur_norm;
        max_index = jj;
      }
    }
    if (U[max_index][j] == traits.zero()) return -1;
    if (j != max_index) {
      std::swap(U[j], U[max_index]);
      std::swap(L[j], L[max_index]);
      std::swap(p[j], p[max_index]);
      positive = !positive;
    }
    for (int i = j + 1; i < n; ++i) {
      T lij = traits.divide(U[i][j], U[j][j]);
      L[i][j] = lij;
      U[i][j] = 0;
      for (int k = j + 1; k < n; ++k)
        traits.minus_assign(U[i][k], U[j][k] * lij);
    }
  }
  for (int i = 0; i < n; ++i) L[i][i] = 1;
  return 0;
}
template <typename T, template <typename> class Ring>
T determinant(const matrix<T, Ring> &A) {
  Ring<T> traits;
  std::vector<int> p;
  bool pos;
  matrix<T, Ring> L, U;
  if (PLU_decompose(A, p, L, U, pos) < 0) return traits.zero();
  T ret = traits.one();
  for (int i = 0; i < A.r(); ++i) traits.time_assign(ret, U[i][i]);
  if (!pos) ret = traits.negate(ret);
  return ret;
}
struct max_clique {
  static const int maxn = 41;
  vector<int> found;
  bool g[maxn][maxn] = {};
  int maxc[maxn];
  bool dfs(vector<int> &clique, const vector<int> &todo) {
    if (todo.empty()) {
      if (clique.size() > found.size()) {
        found = clique;
        return true;
      }
    } else {
      for (int i = 0; i < (int)todo.size(); ++i) {
        if (clique.size() + todo.size() - i <= found.size()) continue;
        int v = todo[i];
        if (clique.size() + maxc[v] <= found.size()) continue;
        vector<int> next;
        for (int j = i + 1; j < (int)todo.size(); ++j) {
          int w = todo[j];
          if (g[v][w]) next.push_back(w);
        }
        clique.push_back(v);
        if (dfs(clique, next)) return true;
        clique.pop_back();
      }
    }
    return false;
  }
  int solve() {
    for (int u = maxn - 1; u >= 0; --u) {
      vector<int> clique = {u};
      vector<int> todo;
      for (int v = 0; v < maxn; ++v)
        if (g[u][v]) todo.push_back(v);
      dfs(clique, todo);
      maxc[u] = (int)found.size();
    }
    return (int)found.size();
  }
};
int main() {
  int n, k;
  scanf("%d%d", &n, &k);
  max_clique mc;
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j) {
      int t;
      scanf("%d", &t);
      mc.g[i][j] = t;
    }
  int m = mc.solve();
  ;
  printf("%.10lf\n", 1.0 * k * k * (m - 1) / 2 / m);
  return 0;
}
