#include <bits/stdc++.h>
using namespace std;
struct vertex {
  int visited;
  int color;
  int parent;
  vector<int> sosedi;
};
vector<vertex> graph;
vector<vertex> bridgesGraph;
vector<int> tin;
vector<int> fup;
stack<int> st;
queue<int> q;
int vertexes, edges, timer;
int bridges = 0;
int maxColor = 0;
void paint(int v) {
  ++maxColor;
  int last = -1;
  while (last != v && !st.empty()) {
    graph[st.top()].color = maxColor;
    last = st.top();
    st.pop();
  }
}
void dfs(int v, int p = -1) {
  graph[v].visited = 1;
  st.push(v);
  tin[v] = fup[v] = timer++;
  for (int i = 0; i < graph[v].sosedi.size(); ++i) {
    int to = graph[v].sosedi[i];
    if (to == p) continue;
    if (graph[to].visited) {
      fup[v] = min(fup[v], tin[to]);
    } else {
      dfs(to, v);
      fup[v] = min(fup[v], fup[to]);
      if (fup[to] > tin[v]) {
        ++bridges;
        paint(to);
      }
    }
  }
}
void buildBridgesGraph(int v, int p = -1) {
  graph[v].visited = 1;
  for (int i = 0; i < graph[v].sosedi.size(); ++i) {
    int to = graph[v].sosedi[i];
    if (to == p) continue;
    if (!graph[to].visited) {
      buildBridgesGraph(to, v);
      if (graph[v].color != graph[to].color) {
        bridgesGraph[bridges - graph[to].color + 2].parent =
            bridges - graph[v].color + 2;
        bridgesGraph[bridges - graph[v].color + 2].sosedi.push_back(
            bridges - graph[to].color + 2);
        bridgesGraph[bridges - graph[to].color + 2].sosedi.push_back(
            bridges - graph[v].color + 2);
      }
    }
  }
}
vector<int> bfs(int v) {
  vector<int> pathArray;
  pathArray.resize(bridges + 2, -1);
  pathArray[v] = 0;
  q.push(v);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int i = 0; i < bridgesGraph[u].sosedi.size(); ++i) {
      if (pathArray[bridgesGraph[u].sosedi[i]] == -1) {
        pathArray[bridgesGraph[u].sosedi[i]] = pathArray[u] + 1;
        q.push(bridgesGraph[u].sosedi[i]);
      }
    }
  }
  return pathArray;
}
int findMaxPath() {
  int maxPath = 0;
  int targetVertex = 0;
  vector<int> pathArray = bfs(1);
  for (int i = 0; i < pathArray.size(); ++i) {
    if (pathArray[i] > maxPath) {
      maxPath = pathArray[i];
      targetVertex = i;
    }
  }
  pathArray = bfs(targetVertex);
  maxPath = 0;
  for (int i = 0; i < pathArray.size(); ++i) {
    if (pathArray[i] > maxPath) {
      maxPath = pathArray[i];
    }
  }
  return maxPath;
}
int main() {
  cin >> vertexes >> edges;
  graph.resize(vertexes + 1);
  tin.resize(vertexes + 1);
  fup.resize(vertexes + 1);
  for (int i = 0; i < edges; ++i) {
    int v1, v2;
    cin >> v1 >> v2;
    graph[v1].sosedi.push_back(v2);
    graph[v2].sosedi.push_back(v1);
  }
  dfs(1);
  paint(1);
  bridgesGraph.resize(bridges + 2);
  for (int i = 1; i <= vertexes; ++i) {
    graph[i].visited = 0;
    if (i < bridges + 2) {
      bridgesGraph[i].parent = i;
    }
  }
  buildBridgesGraph(1);
  cout << endl << findMaxPath();
  return 0;
}
