#include <bits/stdc++.h>
using namespace std;
const int S = 1000000;
char RRR[S];
char *SSR, *UR;
inline char fgc() {
  if (SSR == UR) UR = (SSR = RRR) + fread(RRR, 1, S, stdin);
  return *SSR++;
}
inline void read(int &ur) {
  int ssr = 1;
  char rrr;
  ur = 0;
  while (rrr = getchar(), rrr > '9' || rrr < '0')
    if (rrr == '-') ssr = -1;
  while (rrr >= '0' && rrr <= '9') ur = ur * 10 + rrr - '0', rrr = getchar();
  return (void)(ur *= ssr);
}
inline void write(int ur) {
  if (ur < 0) putchar('-'), ur *= -1;
  if (ur >= 10) write(ur / 10);
  return (void)putchar(ur % 10 + '0');
}
inline void wtn(int ur) {
  write(ur);
  return (void)putchar('\n');
}
inline void wts(int ur) {
  write(ur);
  return (void)putchar(' ');
}
const int MAX = 300005;
int n, m;
int in1, in2, ans = 0;
bool ins[MAX] = {0};
int stk[MAX], dfn[MAX], low[MAX], num[MAX], sum[MAX] = {0}, out[MAX] = {0},
                                            tot = 0, sk = 0;
struct edge {
  int t, nt;
} e[MAX << 1];
struct info {
  int t, ne;
} ee[MAX << 1];
int k = 0, scc = 0, head[MAX] = {0};
int kk = 0, headd[MAX];
int treedis[MAX], treepos = 0, maxtreedis = 0;
bool vis[MAX];
inline void add_edge(int i, int j) {
  e[++k].t = j;
  e[k].nt = head[i];
  head[i] = k;
}
inline void add(int i, int j) {
  ee[++kk].t = j;
  ee[kk].ne = headd[i];
  headd[i] = kk;
}
inline void tarjan(int a, int fa) {
  dfn[a] = low[a] = ++tot;
  stk[++sk] = a, ins[a] = 1;
  for (register int i = head[a]; i; i = e[i].nt) {
    int to = e[i].t;
    if (to == fa) continue;
    if (!dfn[to])
      tarjan(to, a), low[a] = ((low[a]) < (low[to]) ? (low[a]) : (low[to]));
    else if (ins[to])
      low[a] = ((low[a]) < (dfn[to]) ? (low[a]) : (dfn[to]));
  }
  if (dfn[a] == low[a]) {
    scc++;
    int k;
    do {
      k = stk[sk];
      num[k] = scc, sum[scc]++;
      stk[sk] = ins[k] = 0, sk--;
    } while (k != a);
  }
}
inline void bfs(int s) {
  queue<int> q;
  q.push(s);
  while (!q.empty()) {
    int now = q.front();
    q.pop();
    vis[now] = 1;
    for (register int i = headd[now]; i; i = ee[i].ne) {
      int to = ee[i].t;
      if (vis[to]) continue;
      treedis[to] = treedis[now] + 1;
      if (treedis[to] > maxtreedis) {
        maxtreedis = treedis[to];
        treepos = to;
      }
      q.push(to);
    }
  }
  return;
}
int main(void) {
  read(n), read(m);
  for (register int i = 1; i <= m; ++i) {
    read(in1), read(in2);
    add_edge(in1, in2), add_edge(in2, in1);
  }
  for (register int i = 1; i <= n; ++i)
    if (!dfn[i]) tarjan(i, 0);
  for (register int i = 1; i <= n; ++i)
    for (register int j = head[i]; j; j = e[j].nt)
      if (num[e[j].t] != num[i]) add(num[e[j].t], num[i]);
  bfs(1);
  memset(vis, 0, sizeof(vis));
  memset(treedis, 0, sizeof(treedis));
  maxtreedis = 0;
  bfs(treepos);
  wtn(maxtreedis);
  return 0;
}
