#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:256000000")
using namespace std;
typedef long long ll;
void my_return(ll code) { exit(code); }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll my_exp(ll a, ll b, ll MOD = numeric_limits<ll>::max()) {
  a %= MOD;
  if (b == 0) {
    return 1;
  } else {
    return ((b % 2 == 1 ? a : 1) * my_exp(a * a, b / 2, MOD)) % MOD;
  }
}
bool is_prime(ll n) {
  if (n != 2 && n % 2 == 0) {
    return false;
  } else {
    for (int i = 3; (i * i) <= n; i += 2) {
      if (n % i == 0) return false;
    }
    return true;
  }
}
class graph {
 public:
  ll n, m;
  vector<list<pair<ll, ll>>> adj;
  vector<bool> visited;
  void add_edge(ll node1, ll node2, ll weight = 1) {
    adj[node1].push_back(make_pair(node2, weight));
    adj[node2].push_back(make_pair(node1, weight));
    ++m;
  }
  ll dfs(ll curr, ll& ans) {
    visited[curr] = true;
    set<pair<ll, ll>, greater<pair<ll, ll>>> h;
    h.insert(make_pair(0, curr));
    for (decltype(adj[curr].begin()) it = adj[curr].begin();
         it != adj[curr].end(); it++) {
      if (!visited[it->first]) {
        h.insert(make_pair(dfs(it->first, ans), it->first));
      }
    }
    if (h.size() > 1) {
      ll l1, l2;
      l1 = h.begin()->first;
      l2 = (++h.begin())->first;
      if (l1 + l2 > ans) {
        ans = l1 + l2;
      }
    }
    return (h.begin()->first + 1);
  }
  graph(ll a) {
    n = a;
    m = 0;
    adj = vector<list<pair<ll, ll>>>(n);
    visited = vector<bool>(n, false);
  }
};
int main() {
  ios_base::sync_with_stdio(false);
  ll n, m;
  cin >> n >> m;
  graph g(n);
  for (ll i = 0; i < m; ++i) {
    ll a, b;
    cin >> a >> b;
    g.add_edge(a - 1, b - 1);
  }
  ll ans = 0;
  g.dfs(0, ans);
  cout << ans;
  my_return(0);
}
