#include <bits/stdc++.h>
using namespace std;
template <class T>
inline T Abs(const T& x) {
  return x < 0 ? -x : x;
}
template <class T>
inline T Sqr(const T& x) {
  return x * x;
}
const int maxn = 401;
int d[maxn][maxn];
vector<int> atDist[maxn][maxn];
int main() {
  int n, m;
  cin >> n >> m;
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= n; ++j) {
      d[i][j] = n;
    }
  }
  for (int i = 0; i < m; ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    d[u][v] = d[v][u] = 1;
  }
  for (int i = 1; i <= n; ++i) {
    d[i][i] = 0;
  }
  for (int k = 1; k <= n; ++k) {
    for (int i = 1; i <= n; ++i) {
      for (int j = 1; j <= n; ++j) {
        if (d[i][k] + d[k][j] < d[i][j]) {
          d[i][j] = d[i][k] + d[k][j];
        }
      }
    }
  }
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= n; ++j) {
      atDist[i][d[i][j]].push_back(j);
    }
  }
  double best = 0.0;
  for (int u = 1; u <= n; ++u) {
    double uProb = 0.0;
    for (int d1 = 0; d1 < n; ++d1) {
      if (atDist[u][d1].empty()) {
        continue;
      }
      double d1Prob = atDist[u][d1].size() / double(n);
      double firstChoiceProb = 1.0 / atDist[u][d1].size();
      vector<double> whereProb(n + 1, 0.0);
      for (int i : atDist[u][d1]) {
        for (int j : atDist[i][1]) {
          whereProb[j] +=
              (1.0 / atDist[u][d1].size()) * (1.0 / atDist[i][1].size());
        }
      }
      double secondChoiceProbBest = 0.0;
      vector<double> wMax(n, 0.0);
      vector<int> wTouch(n, 0);
      vector<int> vertices = atDist[u][d1];
      if (d1 > 0) {
        vertices.insert(vertices.end(), atDist[u][d1 - 1].begin(),
                        atDist[u][d1 - 1].end());
      }
      if (d1 + 1 < n) {
        vertices.insert(vertices.end(), atDist[u][d1 + 1].begin(),
                        atDist[u][d1 + 1].end());
      }
      for (int v = 1; v <= n; ++v) {
        double secondChoiceProb = 0.0;
        for (int i : vertices) {
          wMax[d[v][i]] = 0.0;
        }
        for (int i : vertices) {
          wMax[d[v][i]] = max(wMax[d[v][i]], whereProb[i]);
        }
        for (int i : vertices) {
          if (wTouch[d[v][i]] != v) {
            wTouch[d[v][i]] = v;
            secondChoiceProb += wMax[d[v][i]];
          }
        }
        secondChoiceProbBest = max(secondChoiceProbBest, secondChoiceProb);
      }
      uProb += d1Prob * max(firstChoiceProb, secondChoiceProbBest);
    }
    best = max(best, uProb);
  }
  printf("%.15lf\n", best);
  return 0;
}
