#include <bits/stdc++.h>
const int MAXN = 5 * (int)1e5;
using namespace std;
struct edge {
  int to, num;
  edge() {}
  edge(int _to, int _num) {
    to = _to;
    num = _num;
  }
};
vector<vector<edge>> graph;
vector<edge> edges;
set<pair<int, int>> bridges;
vector<int> tin, up;
vector<bool> was;
int timer = 0;
int to_start;
vector<int> ranks;
vector<int> p;
void init(int n) {
  ranks.assign(n, 1);
  p.resize(n);
  for (int i = 0; i < n; i++) {
    p[i] = i;
  }
}
int find_root(int n) { return p[n] == n ? n : p[n] = find_root(p[n]); }
void merge(int a, int b) {
  a = find_root(a);
  b = find_root(b);
  if (a == b) return;
  if (ranks[a] < ranks[b]) {
    swap(a, b);
  }
  p[b] = a;
  ranks[a] += ranks[b];
}
void dfs(int v, int p = -1) {
  was[v] = true;
  tin[v] = up[v] = timer++;
  for (edge e : graph[v]) {
    int u = e.to;
    if (e.num == p) continue;
    if (!was[u]) {
      dfs(u, e.num);
      up[v] = min(up[v], up[u]);
      if (tin[v] < up[u]) {
        bridges.insert({v, u});
      } else {
        merge(v, u);
      }
    } else {
      up[v] = min(up[v], tin[u]);
    }
  }
}
vector<vector<int>> tree(MAXN);
void build() {
  for (auto br : bridges) {
    int x = br.first;
    int y = br.second;
    x = find_root(x);
    y = find_root(y);
    to_start = y;
    tree[x].push_back(y);
    tree[y].push_back(x);
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  int n, m;
  cin >> n >> m;
  graph.resize(n);
  was.resize(n);
  tin.resize(n);
  up.resize(n);
  init(n);
  int cur = 0;
  for (int i = 0; i < m; i++) {
    int from, to;
    cin >> from >> to;
    from--;
    to--;
    graph[from].emplace_back(to, cur);
    graph[to].emplace_back(from, cur);
    cur++;
  }
  dfs(0);
  if (bridges.size() == 0) {
    cout << 0 << endl;
    return 0;
  }
  build();
  vector<int> dist1(MAXN, 100000000);
  was.assign(MAXN, false);
  queue<int> bfs;
  bfs.push(to_start);
  was[to_start] = true;
  dist1[to_start] = 0;
  pair<int, int> ans1 = {-1, -1};
  while (!bfs.empty()) {
    int cur = bfs.front();
    bfs.pop();
    for (int u : tree[cur]) {
      if (!was[u]) {
        dist1[u] = dist1[cur] + 1;
        if (dist1[u] > ans1.second) {
          ans1.second = dist1[u];
          ans1.first = u;
        }
        bfs.push(u);
        was[u] = true;
      }
    }
  }
  pair<int, int> ans2 = {-1, -1};
  dist1.assign(n, 100000000);
  was.assign(n, false);
  dist1[ans1.first] = 0;
  was[ans1.first] = true;
  bfs.push(ans1.first);
  while (!bfs.empty()) {
    int cur = bfs.front();
    bfs.pop();
    for (int u : tree[cur]) {
      if (!was[u]) {
        dist1[u] = dist1[cur] + 1;
        if (dist1[u] > ans2.second) {
          ans2.second = dist1[u];
          ans2.first = u;
        }
        bfs.push(u);
        was[u] = true;
      }
    }
  }
  cout << ans2.second << endl;
  return 0;
}
