#include <bits/stdc++.h>
using namespace std;
const int NMAX = 3e5;
map<pair<int, int>, bool> bridges;
class Graph {
  int V;
  list<int> *adj;
  void bridgeUtil(int v, bool visi[], int disc[], int low[], int parent[]);

 public:
  Graph(int V);
  void addEdge(int v, int w);
  void bridge();
};
Graph::Graph(int V) {
  this->V = V;
  adj = new list<int>[V];
}
void Graph::addEdge(int v, int w) {
  adj[v].push_back(w);
  adj[w].push_back(v);
}
void Graph::bridgeUtil(int u, bool visi[], int disc[], int low[],
                       int parent[]) {
  static int time = 0;
  visi[u] = 1;
  disc[u] = low[u] = ++time;
  list<int>::iterator i;
  for (i = adj[u].begin(); i != adj[u].end(); ++i) {
    int v = *i;
    if (!visi[v]) {
      parent[v] = u;
      bridgeUtil(v, visi, disc, low, parent);
      low[u] = min(low[u], low[v]);
      if (low[v] > disc[u]) {
        bridges[{u + 1, v + 1}] = bridges[{v + 1, u + 1}] = 1;
      }
    } else if (v != parent[u])
      low[u] = min(low[u], disc[v]);
  }
}
void Graph::bridge() {
  bool *visi = new bool[V];
  int *disc = new int[V];
  int *low = new int[V];
  int *parent = new int[V];
  for (int i = 0; i < V; i++) {
    parent[i] = -1;
    visi[i] = false;
  }
  for (int i = 0; i < V; i++)
    if (visi[i] == false) bridgeUtil(i, visi, disc, low, parent);
}
vector<int> G[NMAX + 2];
int N, M, dist[NMAX + 2], viz[NMAX + 2];
void dfs(int nod) {
  viz[nod] = 1;
  for (auto x : G[nod]) {
    if (!viz[x]) {
      dist[x] = dist[nod] + bridges[{nod, x}];
      dfs(x);
    }
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> N >> M;
  Graph gr(N);
  for (int i = 1; i <= M; ++i) {
    int x, y;
    cin >> x >> y;
    G[x].push_back(y);
    G[y].push_back(x);
    gr.addEdge(x - 1, y - 1);
  }
  gr.bridge();
  dfs(1);
  int nod = max_element(dist + 1, dist + N + 1) - dist;
  memset(viz, 0, sizeof(viz));
  memset(dist, 0, sizeof(dist));
  dfs(nod);
  cout << *max_element(dist + 1, dist + N + 1) << '\n';
  return 0;
}
