#include <bits/stdc++.h>
#pragma optimize("", off)
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/STACK:36777216")
using namespace std;
template <class T>
void smin(T& a, T val) {
  if (a > val) a = val;
}
template <class T>
void smax(T& a, T val) {
  if (a < val) a = val;
}
template <typename T>
inline std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
  bool first = true;
  os << "[";
  for (auto i : v) {
    if (!first) os << ", ";
    os << i;
    first = false;
  }
  return os << "]";
}
const int N = 3 * 1e5 + 10;
const int M = 3 * 1e5 + 10;
std::vector<int> tree[N];
std::vector<int> graph[N];
int U[M], V[M];
bool isbridge[M];
int visited[N];
int arr[N], T;
int cmpno;
queue<int> Q[N];
int adj(int u, int e) { return U[e] == u ? V[e] : U[e]; }
int dfs0(int u, int edge) {
  visited[u] = 1;
  arr[u] = T++;
  int dbe = arr[u];
  for (int i = 0; i < (int)graph[u].size(); i++) {
    int e = graph[u][i];
    int w = adj(u, e);
    if (!visited[w])
      dbe = min(dbe, dfs0(w, e));
    else if (e != edge)
      dbe = min(dbe, arr[w]);
  }
  if (dbe == arr[u] && edge != -1) isbridge[edge] = true;
  return dbe;
}
void dfs1(int v) {
  int currcmp = cmpno;
  Q[currcmp].push(v);
  visited[v] = 1;
  while (!Q[currcmp].empty()) {
    int u = Q[currcmp].front();
    Q[currcmp].pop();
    for (int i = 0; i < (int)graph[u].size(); i++) {
      int e = graph[u][i];
      int w = adj(u, e);
      if (visited[w]) continue;
      if (isbridge[e]) {
        cmpno++;
        tree[currcmp].push_back(cmpno);
        tree[cmpno].push_back(currcmp);
        dfs1(w);
      } else {
        Q[currcmp].push(w);
        visited[w] = 1;
      }
    }
  }
}
int ans = 0;
int dfs(int curr, int pa) {
  visited[curr] = 1;
  int ma1 = 0, ma2 = 0, ma = 0;
  for (auto i : tree[curr]) {
    if (i == pa) continue;
    ma = dfs(i, curr);
    if (ma > ma1) {
      ma2 = ma1;
      ma1 = ma;
    } else if (ma > ma2) {
      ma2 = ma;
    }
  }
  smax(ans, ma1 + ma2);
  return (ma1 + 1);
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    int x, y;
    cin >> x >> y;
    graph[x].push_back(i);
    graph[y].push_back(i);
    U[i] = x;
    V[i] = y;
  }
  memset(visited, false, sizeof visited);
  for (int i = 1; i <= n; ++i) {
    if (!visited[i]) {
      dfs0(i, -1);
      ++cmpno;
    }
  }
  cmpno = 0;
  memset(visited, false, sizeof visited);
  for (int i = 1; i <= n; ++i) {
    if (!visited[i]) {
      dfs1(i);
      ++cmpno;
    }
  }
  dfs(0, -1);
  cout << ans;
  return 0;
}
