#include <bits/stdc++.h>

#define inf 0x3f3f3f3f

#define MOD 1000000007

#define pb push_back

#define sq(x) ((x)*(x))

#define x first

#define y second

#define eps 1e-9

#define bpt(x) (__builtin_popcount(x))

#define bptl(x) (__builtin_popcountll(x))

#define bit(x, y) (((x)>>(y))&1)

#define bclz(x) (__builtin_clz(x))

#define bclzl(x) (__builtin_clzll(x))

#define bctz(x) (__builtin_ctz(x))

#define bctzl(x) (__builtin_ctzll(x))

#define PQ priority_queue<pii, vector<pii>, greater<pii> >

using namespace std;

typedef long long INT;

typedef vector<int> VI;

typedef pair<int, int> pii;

typedef pair<pii, int> pi3;

typedef double DO;

template<typename T, typename U> inline void smin(T &a, U b) {if (a>b) a=b;}

template<typename T, typename U> inline void smax(T &a, U b) {if (a<b) a=b;}

template<class T>inline void gn(T &x) {char c, sg=0; while (c=getchar(), (c>'9' || c<'0') && c!='-');for((c=='-'?sg=1, c=getchar():0), x=0; c>='0' && c<='9'; c=getchar()) x=(x<<1)+(x<<3)+c-'0';if (sg) x=-x;}

template<class T, class T1>inline void gn(T &x, T1 &y) {gn(x); gn(y);}

template<class T, class T1, class T2>inline void gn(T &x, T1 &y, T2 &z) {gn(x); gn(y); gn(z);}

template<class T>inline void print(T x) {if (x<0) {putchar('-');return print(-x);}if (x<10) {putchar('0'+x);return;} print(x/10);putchar(x%10+'0');}

template<class T>inline void printsp(T x) {print(x); putchar(' ');}

template<class T>inline void println(T x) {print(x); putchar('\n');}

template<class T, class U>inline void print(T x, U y) {printsp(x); println(y);}

template<class T, class U, class V>inline void print(T x, U y, V z) {printsp(x); printsp(y); println(z);}

int power(int a, int b, int m, int ans=1) {

	for (; b; b>>=1, a=1LL*a*a%m) if (b&1) ans=1LL*ans*a%m;

	return ans;

}

#define NN 310000

#define MM 310000

int head[NN], to[2*MM], nxt[2*MM], vst[NN], low[NN], bel[NN];

int top, st[NN];

int ind, cnt;

void dfs(int u, int pre=-1){

	vst[u]=low[u]=++ind;

	st[++top]=u;

	for(int e=head[u]; e!=-1; e=nxt[e]){

		int v=to[e];

		if(!vst[v]) dfs(v, e), low[u]=min(low[u], low[v]);

		else if((e^pre)!=1) low[u]=min(low[u], vst[v]);

	}

	if(vst[u]==low[u]){

		++cnt;

		while(1){

			bel[st[top]]=cnt;

			if(st[top--]==u) break;

		}

	}

}

int E;

void add_edge(int u, int v) {

	to[E]=v; nxt[E]=head[u]; head[u]=E++;

}

pii edge[NN];

VI adj[NN];

pii dfs1(int u, int pa=-1) {

	pii a=pii(-1, u);

	for (int i=0; i<adj[u].size(); i++) {

		int v=adj[u][i];

		if (v==pa) continue;

		smax(a, dfs1(v, u));

	}

	a.x++;

	return a;

}

pii p[NN];

int main() {

#ifndef ONLINE_JUDGE

	freopen("in.in", "r", stdin);

	freopen("out.out", "w", stdout);

#endif

	int n, m;

	gn(n, m);

	memset(head, -1, sizeof head);

	for (int i=0; i<m; i++) {

		int u, v;

		gn(u, v);

		p[i]=pii(u, v);

		add_edge(u, v); add_edge(v, u);

	}

	for (int i=1; i<=n; i++) if (!vst[i]) dfs(i);

	for (int i=0; i<m; i++) {

		int u=bel[p[i].x], v=bel[p[i].y];

		if (u==v) continue;

		adj[u].pb(v); adj[v].pb(u);

	}

	pii a=dfs1(1);

	pii b=dfs1(a.y);

	println(b.x);

	return 0;

}


#include <bits/stdc++.h>

#define inf 0x3f3f3f3f

#define INF 0x3f3f3f3f3f3f3f3fLL

#define mod 1000000007

#define hmod 911382323

#define pb push_back

#define sq(x) ((x)*(x))

#define sz(a) ((int)a.size())

#define LEN(a) (a.length())

#define x first

#define y second

#define ls (u<<1)

#define rs (ls + 1)

#define mid (st + ed >> 1)

#define eps 1e-8

#define bpt(x) (__builtin_popcount(x))

#define bptl(x) (__builtin_popcountll(x))

#define bit(x, y) (((x)>>(y))&1)

#define bclz(x) (__builtin_clz(x))

#define bclzl(x) ((x) ? (__builtin_clzll(x)) : 0)

#define bctz(x) (__builtin_ctz(x))

#define bctzl(x) (__builtin_ctzll(x))

#define rands(n) (rand()%n+1)

#define rand0(n) (rands(n)-1)

#define Rands(n) ((INT)rand()*rand()%n+1)

#define Rand0(n) (Rands(n)-1)

#define PQ priority_queue<pii, vector<pii>, greater<pii> >

#define rep(i, a, b) for(int i=a; i<b; i++)

#define eprintf(...) fprintf(stderr, __VA_ARGS__)

#define shit(a) (1 << (a))

#define all(a) ((a).begin(), (a).end())

#define rev(a) (power(a, mod-2, mod))

using namespace std;

typedef long long INT;

typedef unsigned long long UINT;

typedef unsigned int uint;

typedef complex<double> Complex;

typedef double DO;

typedef vector<int> VI;

typedef pair<int, int> pii;

typedef pair<INT, INT> PII;

typedef pair<pii, int> ppi;

typedef pair<int, pii> pip;

typedef pair<DO, DO> pdd;

typedef pair<int, DO> pid;

typedef pair<DO, int> pdi;

template<typename T, typename U> inline void smin(T &a, U b) {if (a>b) a=b;}

template<typename T, typename U> inline void smax(T &a, U b) {if (a<b) a=b;}

template<class T>inline void gn(T &x) {char c, sg=0; while (c=getchar(), (c>'9' || c<'0') && c!='-');for((c=='-'?sg=1, c=getchar():0), x=0; c>='0' && c<='9'; c=getchar()) x=(x<<1)+(x<<3)+c-'0';if (sg) x=-x;}

template<class T>inline void print(T x) {if (x<0) {putchar('-');return print(-x);}if (x<10) {putchar('0'+x);return;} print(x/10);putchar(x%10+'0');}

template<class T, class T1>inline void gn(T &x, T1 &y) {gn(x); gn(y);}

template<class T, class T1, class T2>inline void gn(T &x, T1 &y, T2 &z) {gn(x); gn(y); gn(z);}

template <class T> inline void println(T x) {print(x); putchar('\n');}

template <class T> inline void printsp(T x) {print(x); putchar(' ');}

template <class T1, class T2> inline void print(T1 x1, T2 x2) {printsp(x1), println(x2);}

template <class T1, class T2, class T3> inline void print(T1 x1, T2 x2, T3 x3) {printsp(x1), printsp(x2), println(x3);}

template <class T1, class T2, class T3, class T4> inline void print(T1 x1, T2 x2, T3 x3, T4 x4) {printsp(x1), printsp(x2), printsp(x3), println(x4);}

int power(int a, int b, int m, int ans=1) {

	for (; b; b>>=1, a=1LL*a*a%m) if (b&1) ans=1LL*ans*a%m;

	return ans;

}

#define NN 600011

int vst[NN], low[NN], bel[NN], st[NN];

int cnt, top, ind;

int head[NN], nxt[NN], to[NN];

int E;

vector<int> adj[NN];

void dfs(int u, int pre=-1){

	vst[u]=low[u]=++ind;

	st[++top]=u;

	for(int e=head[u]; e!=-1; e=nxt[e]){

		int v=to[e];

		if(!vst[v]) dfs(v, e), low[u]=min(low[u], low[v]);

		else if((pre^e)!=1) low[u]=min(low[u], vst[v]);

	}

	if(vst[u]==low[u]){

		++cnt;

		while(1){

			bel[st[top]]=cnt;

			if(st[top--]==u) break;

		}

	}

}

int deep[NN];

void solve(int u, int fa=0) {

	deep[u] = deep[fa] + 1;

	for(int i=0; i<sz(adj[u]); i++) {

		int v=adj[u][i];

		if(v==fa) continue;

		solve(v, u);

	}

}

int main() {

#ifndef ONLINE_JUDGE

	freopen("in.in", "r", stdin);

	freopen("out.out", "w", stdout);

#endif

	memset(head, -1, sizeof head);

	int n, m;

	cin >> n >> m;

	for(int i=0; i<m; i++) {

		int u, v;

		gn(u, v);

		nxt[E] = head[u]; to[E] = v; head[u] = E++;

		nxt[E] = head[v]; to[E] = u; head[v] = E++;

	}

	dfs(1);

	for(int u=1; u<=n; u++) {

		for(int e=head[u]; ~e; e=nxt[e]) {

			int v=to[e];

			if(bel[u] != bel[v]) adj[bel[u]].pb(bel[v]);

		}

	}

	solve(1);

	int mx=0, id;

	for(int i=1; i<=cnt; i++) {

		if(deep[i] > mx) mx = deep[i], id=i;

		deep[i] = 0;

	}

	solve(id);

	mx =0;

	for(int i=1; i<=cnt; i++) smax(mx, deep[i]);

	cout << mx - 1 << endl;

	return 0;

}


#include <bits/stdc++.h>

using namespace std;

vector<int>vec[3*(int)1e5+5];
int disc[3*(int)1e5+5],low[3*(int)1e5+5],cnt=0,last=-1;
bool isInc[3*(int)1e5+5];
map<pair<int,int>,bool>M;

void findB(int u,int par){
    disc[u]=low[u]=++cnt;

    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];
        if(!disc[v]){
            findB(v,u);
            low[u]=min(low[u],low[v]);
        }
        else if(v!=par)low[u]=min(low[u],disc[v]);

        if(low[u]<low[v]){
            last=u;
            M[make_pair(u,v)]=M[make_pair(v,u)]=true;
            isInc[u]=isInc[v]=1;
        }
    }
}
vector<int>bridge[3*(int)1e5+5];
void makeG(int u){
    disc[u]=true;
    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];

        if(!disc[v]){
            makeG(v);
            if(isInc[u] && isInc[v]){
                bridge[u].push_back(v);
                bridge[v].push_back(u);
            }
        }
    }
}
pair<int,int>ser(int u,int par,int cnt){
    pair<int,int>ret=make_pair(cnt,u);
    for(int i=0;i<bridge[u].size();i++){
        int v=bridge[u][i];
        if(v!=par){
            ret=max(ret,ser(v,u,(M[make_pair(u,v)]==1)?cnt+1:cnt));
        }
    }
    return ret;
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0,u,v;i<m;i++){
        scanf("%d %d",&u,&v);
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    findB(1,-1);
    if(last==-1){
        printf("0\n");
        return 0;
    }
    memset(disc,0,sizeof(disc));
    makeG(last);

    pair<int,int>ret=ser(last,-1,0);
    //cout<<ret.first<<" "<<ret.second<<endl;
    ret=ser(ret.second,-1,0);
    printf("%d\n",ret.first);

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int>vec[3*(int)1e5+5];
int disc[3*(int)1e5+5];
int low[3*(int)1e5+5];
int root=-1;

bool isInc[3*(int)1e5+5];
map<pair<int,int>,int>M;
vector<pair<int,int> >bridge[3*(int)1e5+5];

void findB(int u,int par){
    static int cnt=0;
    disc[u]=low[u]=++cnt;

    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];
        if(!disc[v]){
            findB(v,u);
            low[u]=min(low[u],low[v]);

            if(low[u]<low[v]){
                isInc[u]=isInc[v]=1;
                M[make_pair(u,v)]=M[make_pair(v,u)]=1;

                root=u;
            }
        }
        else if(v!=par)low[u]=min(low[u],disc[v]);
    }
}

void makeG(int u,int pre){
    disc[u]=1;
    if(isInc[u])pre=u;

    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];

        if(!disc[v]){
            makeG(v,pre);
            if(isInc[pre] && isInc[v]){
                bridge[pre].push_back(make_pair(v,M[make_pair(pre,v)]));
                bridge[v].push_back(make_pair(pre,M[make_pair(pre,v)]));
            }
        }
    }
}

pair<int,int>searchInTree(int u,int par,int cnt){
    pair<int,int>ret=make_pair(cnt,u);
    for(int i=0;i<bridge[u].size();i++){
        int v=bridge[u][i].first;
        int w=bridge[u][i].second;

        if(v!=par)ret=max(ret,searchInTree(v,u,cnt+w));
    }
    return ret;
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0,u,v;i<m;i++){
        scanf("%d %d",&u,&v);
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    findB(1,-1);

    if(root==-1){
        printf("0\n");
        return 0;
    }
    memset(disc,0,sizeof(disc));
    makeG(root,0);
    printf("%d\n",searchInTree(searchInTree(root,-1,0).second,-1,0).first);

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int>vec[3*(int)1e5+5];
int disc[3*(int)1e5+5],low[3*(int)1e5+5],cnt=0,last=-1;
bool isInc[3*(int)1e5+5];
map<pair<int,int>,bool>M;

void findB(int u,int par){
    disc[u]=low[u]=++cnt;

    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];
        if(!disc[v]){
            findB(v,u);
            low[u]=min(low[u],low[v]);

            if(low[u]<low[v]){
                last=u;
                isInc[u]=isInc[v]=1;
                M[make_pair(u,v)]=M[make_pair(v,u)]=true;
            }
        }
        else if(v!=par)low[u]=min(low[u],disc[v]);
    }
}

vector<pair<int,int> >bridge[3*(int)1e5+5];
void makeG(int u,int pre){
    disc[u]=1;
    if(isInc[u])pre=u;

    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];

        if(!disc[v]){
            if(isInc[pre] && isInc[v]){
                bridge[pre].push_back(make_pair(v,M[make_pair(pre,v)]));
                bridge[v].push_back(make_pair(pre,M[make_pair(pre,v)]));
            }
            makeG(v,last);
        }
    }
}
pair<int,int>ser(int u,int par,int cnt){
    pair<int,int>ret=make_pair(cnt,u);
    for(int i=0;i<bridge[u].size();i++){
        int v=bridge[u][i].first;
        int w=bridge[u][i].second;
        if(v!=par){
            ret=max(ret,ser(v,u,cnt+w));
        }
    }
    return ret;
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0,u,v;i<m;i++){
        scanf("%d %d",&u,&v);
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    findB(1,-1);
    if(last==-1){
        printf("0\n");
        return 0;
    }
    memset(disc,0,sizeof(disc));
    makeG(last,0);

    pair<int,int>ret=ser(last,-1,0);
    ret=ser(ret.second,-1,0);
    printf("%d\n",ret.first);

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int>vec[3*(int)1e5+5];
int disc[3*(int)1e5+5],low[3*(int)1e5+5],cnt=0,last=-1;
bool isInc[3*(int)1e5+5];
map<pair<int,int>,bool>M;

void findB(int u,int par){
    disc[u]=low[u]=++cnt;

    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];
        if(!disc[v]){
            findB(v,u);
            low[u]=min(low[u],low[v]);

            if(low[u]<low[v]){
                last=u;
                isInc[u]=isInc[v]=1;
                M[make_pair(u,v)]=M[make_pair(v,u)]=true;
            }
        }
        else if(v!=par)low[u]=min(low[u],disc[v]);
    }
}

vector<pair<int,int> >bridge[3*(int)1e5+5];
void makeG(int u){
    disc[u]=1;
    for(int i=0;i<vec[u].size();i++){
        if(!disc[vec[u][i]])makeG(vec[u][i]);

        int v=vec[u][i];
        if(isInc[u] && isInc[v]){
            bridge[u].push_back(make_pair(v,M[make_pair(u,v)]));
            bridge[v].push_back(make_pair(u,M[make_pair(u,v)]));
        }
    }
}
pair<int,int>ser(int u,int par,int cnt){
    pair<int,int>ret=make_pair(cnt,u);
    for(int i=0;i<bridge[u].size();i++){
        int v=bridge[u][i].first;
        int w=bridge[u][i].second;
        if(v!=par){
            ret=max(ret,ser(v,u,cnt+w));
        }
    }
    return ret;
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0,u,v;i<m;i++){
        scanf("%d %d",&u,&v);
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    findB(1,-1);
    if(last==-1){
        printf("0\n");
        return 0;
    }
    memset(disc,0,sizeof(disc));
    makeG(last);

    pair<int,int>ret=ser(last,-1,0);
    ret=ser(ret.second,-1,0);
    printf("%d\n",ret.first);

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int>vec[3*(int)1e5+5];
int disc[3*(int)1e5+5],low[3*(int)1e5+5],cnt=0,last=-1;
bool isInc[3*(int)1e5+5];
map<pair<int,int>,bool>M;

void findB(int u,int par){
    disc[u]=low[u]=++cnt;

    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];
        if(!disc[v]){
            findB(v,u);
            low[u]=min(low[u],low[v]);
            if(low[u]<low[v]){
                last=u;
                M[make_pair(u,v)]=M[make_pair(v,u)]=true;
                isInc[u]=isInc[v]=1;
            }
        }
        else if(v!=par)low[u]=min(low[u],disc[v]);
    }
}
vector<int>bridge[3*(int)1e5+5];
void makeG(int u){
    disc[u]=true;
    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];

        if(!disc[v]){
            makeG(v);
            if(isInc[u] && isInc[v]){
                bridge[u].push_back(v);
                bridge[v].push_back(u);
            }
        }
    }
}
pair<int,int>ser(int u,int par,int cnt){
    pair<int,int>ret=make_pair(cnt,u);
    for(int i=0;i<bridge[u].size();i++){
        int v=bridge[u][i];
        if(v!=par){
            ret=max(ret,ser(v,u,(M[make_pair(u,v)]==1)?cnt+1:cnt));
        }
    }
    return ret;
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0,u,v;i<m;i++){
        scanf("%d %d",&u,&v);
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    findB(1,-1);
    if(last==-1){
        printf("0\n");
        return 0;
    }
    memset(disc,0,sizeof(disc));
    makeG(last);

    pair<int,int>ret=ser(last,-1,0);
    //cout<<ret.first<<" "<<ret.second<<endl;
    ret=ser(ret.second,-1,0);
    printf("%d\n",ret.first);

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int>vec[3*(int)1e5+5];
int disc[3*(int)1e5+5];
int low[3*(int)1e5+5];
int root=-1;

bool isInc[3*(int)1e5+5];
map<pair<int,int>,int>M;
vector<pair<int,int> >bridge[3*(int)1e5+5];

void findB(int u,int par){
    static int cnt=0;
    disc[u]=low[u]=++cnt;

    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];
        if(!disc[v]){
            findB(v,u);
            low[u]=min(low[u],low[v]);

            if(disc[u]<low[v]){
                isInc[u]=isInc[v]=1;
                M[make_pair(u,v)]=M[make_pair(v,u)]=1;

                root=u;
            }
        }
        else if(v!=par)low[u]=min(low[u],disc[v]);
    }
}

void makeG(int u,int pre){
    disc[u]=1;
    if(isInc[u])pre=u;

    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];

        if(!disc[v]){
            makeG(v,pre);
            if(isInc[pre] && isInc[v]){
                bridge[pre].push_back(make_pair(v,M[make_pair(pre,v)]));
                bridge[v].push_back(make_pair(pre,M[make_pair(pre,v)]));
            }
        }
    }
}

pair<int,int>searchInTree(int u,int par,int cnt){
    pair<int,int>ret=make_pair(cnt,u);
    for(int i=0;i<bridge[u].size();i++){
        int v=bridge[u][i].first;
        int w=bridge[u][i].second;

        if(v!=par)ret=max(ret,searchInTree(v,u,cnt+w));
    }
    return ret;
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0,u,v;i<m;i++){
        scanf("%d %d",&u,&v);
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    findB(1,-1);

    if(root==-1){
        printf("0\n");
        return 0;
    }
    memset(disc,0,sizeof(disc));
    makeG(root,0);
    printf("%d\n",searchInTree(searchInTree(root,-1,0).second,-1,0).first);

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int MM=100013;
vector<int> W[MM];
vector<int> D[MM];
int low[MM];
int v[MM];
int pre[MM];
int t=1;
int par[MM];
vector<pair<int,int> > Mosty;

int Find(int x)
{
    if(par[x]!=x)
    {
        par[x]=Find(par[x]);
    }
    return par[x];
}

void Union(int a, int b)
{
    par[Find(a)]=Find(b);
}

void DFS(int w, int par)
{
    v[w]=1;
    pre[w]=t;
    low[w]=t;
    t++;
    for(int i=0; i<W[w].size(); i++)
    {
        if(W[w][i]!=par)
        {
            if(v[W[w][i]]==1)
            {
                low[w]=min(low[w],pre[W[w][i]]);
            }
            else
            {
                DFS(W[w][i],w);
                low[w]=min(low[w],low[W[w][i]]);
            }
        }
    }
    if(par!=-1)
    {
        if(pre[w]==low[w])
        {
            Mosty.push_back(make_pair(w,par));
        }
        else
        {
            Union(w,par);
        }
    }
}
int st;
void build()
{
    for(int i=0; i<Mosty.size(); i++)
    {
        pair<int,int> a=Mosty[i];
        int x=Find(a.first);
        int y=Find(a.second);
        st=x;
        D[x].push_back(y);
        D[y].push_back(x);
    }
}

int deep=-1;
int M=-1;
int best;
void dfs(int w,int par)
{
    deep++;
    if(M<deep)
    {
        best=w;
        M=deep;
    }
    for(int i=0; i<D[w].size(); i++)
    {
        if(D[w][i]!=par)
        {
            dfs(D[w][i],w);
        }
    }
    deep--;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int n,m,a,b;
    cin>>n>>m;
    for(int i=1; i<=n; i++)
        par[i]=i;
    for(int i=1; i<=m; i++)
    {
        cin>>a>>b;
        W[a].push_back(b);
        W[b].push_back(a);
    }
    DFS(1,-1);
    build();
    dfs(st,-1);
    dfs(best,-1);
    cout<<M;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int MM=300013;
vector<int> W[MM];
vector<int> D[MM];
int low[MM];
int v[MM];
int pre[MM];
int t=1;
int par[MM];
vector<pair<int,int> > Mosty;

int Find(int x)
{
    if(par[x]!=x)
    {
        par[x]=Find(par[x]);
    }
    return par[x];
}

void Union(int a, int b)
{
    par[Find(a)]=Find(b);
}

void DFS(int w, int par)
{
    v[w]=1;
    pre[w]=t;
    low[w]=t;
    t++;
    for(int i=0; i<W[w].size(); i++)
    {
        if(W[w][i]!=par)
        {
            if(v[W[w][i]]==1)
            {
                low[w]=min(low[w],pre[W[w][i]]);
            }
            else
            {
                DFS(W[w][i],w);
                low[w]=min(low[w],low[W[w][i]]);
            }
        }
    }
    if(par!=-1)
    {
        if(pre[w]==low[w])
        {
            Mosty.push_back(make_pair(w,par));
        }
        else
        {
            Union(w,par);
        }
    }
}
int st;
void build()
{
    for(int i=0; i<Mosty.size(); i++)
    {
        pair<int,int> a=Mosty[i];
        int x=Find(a.first);
        int y=Find(a.second);
        st=x;
        D[x].push_back(y);
        D[y].push_back(x);
    }
}

int deep=-1;
int M=-1;
int best;
void dfs(int w,int par)
{
    deep++;
    if(M<deep)
    {
        best=w;
        M=deep;
    }
    for(int i=0; i<D[w].size(); i++)
    {
        if(D[w][i]!=par)
        {
            dfs(D[w][i],w);
        }
    }
    deep--;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int n,m,a,b;
    cin>>n>>m;
    for(int i=1; i<=n; i++)
        par[i]=i;
    for(int i=1; i<=m; i++)
    {
        cin>>a>>b;
        W[a].push_back(b);
        W[b].push_back(a);
    }
    DFS(1,-1);
    build();
    dfs(st,-1);
    dfs(best,-1);
    cout<<M;
    return 0;
}


#include <bits/stdc++.h>
#ifdef LOCAL
#include <debug.h>
#else
#define debug(x) ((void)0)
#define range(x, y) ((void)0)
#define endln ((void)0)
#endif

using namespace std;

const int maxn = 3e5 + 5;

int n, m;
vector<int> adj[maxn];
int num[maxn], low[maxn], cnt;
stack<int> st;
int comp[maxn], comps;
vector<int> tree[maxn];

void dfs(int u, int p = 0) {
    num[u] = low[u] = ++cnt;
    st.push(u);
    for (int i = 0; i < adj[u].size(); ++i) {
        int v = adj[u][i];
        if (v != p) {
            if (num[v]) {
                low[u] = min(low[u], num[v]);
            }
            else {
                dfs(v, u);
                low[u] = min(low[u], low[v]);
            }
        }
    }
    if (num[u] == low[u]) {
        ++comps;
        int v;
        do {
            v = st.top(), st.pop();
            num[v] = n, comp[v] = comps;
            for (int i = 0; i < adj[v].size(); ++i) {
                int w = adj[v][i];
                if (comp[w] != 0 && comp[w] != comp[v]) {
                    tree[comp[v]].push_back(comp[w]);
                    tree[comp[w]].push_back(comp[v]);
                }
            }
        }
        while (v != u);
    }
}

int lev[maxn];

int dfs1(int u, int p = 0) {
    lev[u] = lev[p] + 1;
    int ans = u;
    for (int i = 0; i < tree[u].size(); ++i) {
        int v = tree[u][i];
        if (v != p) {
            int w = dfs1(v, u);
            if (lev[w] > lev[ans]) {
                ans = w;
            }
        }
    }
    return ans;
}

int main() {
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    for (int i = 1; i <= n; ++i) {
        if (!num[i]) {
            dfs(i);
        }
    }

    int a = dfs1(1);
    a = dfs1(a);
    int ans = lev[a] - 1;
    printf("%d\n", ans);
    return 0;
}


#include <bits/stdc++.h>
#ifdef LOCAL
#include <debug.h>
#else
#define debug(x) ((void)0)
#define range(x, y) ((void)0)
#define endln ((void)0)
#endif

using namespace std;

const int maxn = 2e5 + 5;

int n, m;
vector<int> adj[maxn];
int num[maxn], low[maxn], cnt;
stack<int> st;
int comp[maxn], comps;
vector<int> tree[maxn];

void dfs(int u, int p = 0) {
    num[u] = low[u] = ++cnt;
    st.push(u);
    for (int i = 0; i < adj[u].size(); ++i) {
        int v = adj[u][i];
        if (v != p) {
            if (num[v]) {
                low[u] = min(low[u], num[v]);
            }
            else {
                dfs(v, u);
                low[u] = min(low[u], low[v]);
            }
        }
    }
    if (num[u] == low[u]) {
        ++comps;
        int v;
        do {
            v = st.top(), st.pop();
            num[v] = n, comp[v] = comps;
            for (int i = 0; i < adj[v].size(); ++i) {
                int w = adj[v][i];
                if (comp[w] != 0 && comp[w] != comp[v]) {
                    tree[comp[v]].push_back(comp[w]);
                    tree[comp[w]].push_back(comp[v]);
                }
            }
        }
        while (v != u);
    }
}

int lev[maxn];

int dfs1(int u, int p = 0) {
    lev[u] = lev[p] + 1;
    int ans = u;
    for (int i = 0; i < tree[u].size(); ++i) {
        int v = tree[u][i];
        if (v != p) {
            int w = dfs1(v, u);
            if (lev[w] > lev[ans]) {
                ans = w;
            }
        }
    }
    return ans;
}

int main() {
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    for (int i = 1; i <= n; ++i) {
        if (!num[i]) {
            dfs(i);
        }
    }

    int a = dfs1(1);
    a = dfs1(a);
    int ans = lev[a] - 1;
    printf("%d\n", ans);
    return 0;
}


#include<bits/stdc++.h>
#define test printf("test\n");
#define L long long
#define pb push_back
#define P printf
using namespace std;
const int maxn = 300000 + 10;

int n,m;
vector<int> e[maxn];
vector<int> e2[maxn];
stack<int> s;
int dfn[maxn],low[maxn],vis[maxn],cnt;
int color[maxn],cid;
int dis[maxn];

void addedge(int a,int b)
{
	e[a].push_back(b);
	e[b].push_back(a);
}

void addedge2(int a,int b)
{
	e2[a].push_back(b);
	e2[b].push_back(a);
}

void tarjan(int u,int fa)
{
	dfn[u]=low[u]=++cnt;
	vis[u]=1;
	s.push(u);

	for(int i=0,v;i<e[u].size();i++)
	{
		v=e[u][i];
		if(v==fa)
			continue;
		if(!vis[v])
		{
			tarjan(v,u);
			low[u]=min(low[u],low[v]);
		}
		else
			low[u]=min(low[u],dfn[v]);
	}

	if(dfn[u]==low[u])
	{
		cid++;
		int v;
		while(!s.empty())
		{
			v=s.top();
			s.pop();
			vis[v]=2;
			color[v]=cid;
			if(v==u) break;
		}
	}
}

void dfs(int u,int fa)
{
	for(int i=0,v;i<e2[u].size();i++)
	{
		v=e2[u][i];
		if(v!=fa)
		{
			dis[v]=dis[u]+1;
			dfs(v,u);
		}
	}
}

void solve()
{
	for(int i=1;i<=n;i++)
		if(!vis[i]) tarjan(i,0);

	for(int u=1,v;u<=n;u++)
	{
		for(int i=0;i<e[u].size();i++)
		{
			v=e[u][i];
			if(color[u]!=color[v]&&v>u)
				addedge2(color[u],color[v]);
		}
	}
	//test
	//printf("%d\n",cid);

	int v=1,p=1;
	dfs(1,0);
	for(int i=2;i<=cid;i++)
		if(dis[i]>dis[v]) v=i;
	memset(dis,0,sizeof(dis));

	dfs(v,0);
	for(int i=2;i<=cid;i++)
		if(dis[i]>dis[p]) p=i;

	printf("%d\n",dis[p]);
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1,u,v;i<=m;i++)
	{
		scanf("%d%d",&u,&v);
		addedge(u,v);
	}
	solve();

	return 0;
}


//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=1e6+7;
int n,m,now[maxn];

template<typename T>void read(T& aa) {
	aa=0;char cc=getchar();T ff=1;
	while((cc!='-')&&(cc<'0'||cc>'9')) cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

int fir[maxn],nxt[2*maxn],to[2*maxn],e=0;
void add(int x,int y) {
	to[++e]=y;nxt[e]=fir[x];fir[x]=e;
	to[++e]=x;nxt[e]=fir[y];fir[y]=e;
}

int FIR[maxn],NXT[2*maxn],TO[2*maxn],E=0;
void ADD(int x,int y) {
//	printf("ADD:%d->%d\n",x,y);
	TO[++E]=y;NXT[E]=FIR[x];FIR[x]=E;
}

int dfn[maxn],low[maxn],dfn_clock;
int zz[maxn],top;
int bel[maxn],toth;
vector<int> G[maxn];
void tj(int pos,int f) {
	dfn[pos]=low[pos]=++dfn_clock;
	int y,z,bot=top; zz[++top]=pos;
	for(y=fir[pos];y;y=nxt[y]) {
		if((z=to[y])==f) continue;
		if(dfn[z]) {
			low[pos]=min(low[pos],dfn[z]);
			continue;
		}
		tj(z,pos); low[pos]=min(low[pos],low[z]);
	}
	if(dfn[pos]==low[pos]) {
		++toth;
		For(i,bot+1,top) {
			bel[zz[i]]=toth;
			G[toth].push_back(zz[i]);
		}
		top=bot;
	}
}

int len[maxn],ans;
void dfs(int pos,int f) {
	int l=len[pos]=0,y,z;
	for(y=FIR[pos];y;y=NXT[y]) {
		if((z=TO[y])==f) continue;
		dfs(z,pos);
		if(len[z]>len[pos]) l=len[pos],len[pos]=len[z];
		else if(len[z]>l) l=len[z];
	}
	ans=max(ans,l+len[pos]);
	++len[pos];
}

int main() {
	read(n); read(m);
	int x,y,z,s;
	For(i,1,m) {
		read(x); read(y);
		add(x,y);
	}
	tj(1,0);
	For(i,1,toth) {
		s=G[i].size(); now[i]=i;
		For(j,0,s-1) {
			x=G[i][j];
			for(y=fir[x];y;y=nxt[y]) {
				if(now[z=bel[to[y]]]==i) continue;
				ADD(i,z); now[z]=i;
			}
		}
	}
	dfs(1,0);
	printf("%d\n",ans);
	return 0;
}


#include <cstdio>
#include <cstring>

#define Maxn 300005
#define Maxe 600005

#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))

inline int read() {
	char c = getchar();
	int n = 0;
	while (c < '0' || c > '9') {
		c = getchar();;
	}
	while (c >= '0' && c <= '9') {
		n = (n << 1) + (n << 3) + (c ^ 48);
		c = getchar();
	}
	return n;
}

struct List {
	int len, fst[Maxn], nxt[Maxe], v[Maxe];
	inline void init(int d) {
		for (int i = 1; i <= d; i++) {
			fst[i] = -1;
		}
		len = 0;
	}
	inline void insert(int _u, int _v) {
		v[len] = _v;
		nxt[len] = fst[_u];
		fst[_u] = len++;
	}
};

List L, G;
int n, m;
int t, vs, dfn[Maxn], low[Maxn], stc[Maxn], col[Maxn];
int ans, q[Maxn], dep[Maxn];
bool ins[Maxn];

void Tarjan(int u, int fth) {
	dfn[u] = low[u] = ++t;
	ins[u] = true;
	stc[++vs] = u;
	int vt = vs;
	for (int i = L.fst[u]; i != -1; i = L.nxt[i]) {
		int v = L.v[i];
		if (v != fth) {
			if (dfn[v] == 0) {
				Tarjan(v, u);
				low[u] = Min(low[u], low[v]);
			} else if (ins[v]) {
				low[u] = Min(low[u], dfn[v]);
			}
		}
	}
	if (dfn[u] == low[u]) {
		for (int i = vt; i <= vs; i++) {
			col[stc[i]] = u;
			ins[stc[i]] = false;
		}
		vs = vt - 1;
	}
}

void Bfs(int d) {
	ans = 0;
	memset(dep, 0, sizeof(dep));
	dep[0] = -1;
	q[1] = d;
	for (int l = 1, r = 1; l <= r; l++) {
		int u = q[l];
		if (dep[ans] < dep[u]) {
			ans = u;
		}
		for (int i = L.fst[u]; i != -1; i = G.nxt[i]) {
			int v = L.v[i];
			if (dep[v] == 0) {
				dep[v] = dep[u] + 1;
				q[++r] = v;
			}
		}
	}
}

int main() {
	n = read(), m = read();
	L.init(n);
	for (int i = 1; i <= m; i++) {
		int u = read(), v = read();
		L.insert(u, v);
		L.insert(v, u);
	}
	for (int i = 1; i <= n; i++) {
		if (dfn[i] == 0) {
			Tarjan(i, 0);
		}
	}
	G.init(n);
	for (int u = 1; u <= n; u++) {
		for (int i = L.fst[u]; i != -1; i = L.nxt[i]) {
			int v = L.v[i];
			if (col[u] != col[v]) {
				G.insert(col[u], col[v]);
			}
		}
	}
	Bfs(1);
	Bfs(ans);
	printf("%d\n", dep[ans]);
	return 0;
}

// By Sooke.
// CF1000E We Need More Bosses.


#include <cstdio>
#include <cstring>

#define Maxn 300005
#define Maxe 600005

#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))

inline int read() {
	char c = getchar();
	int n = 0;
	while (c < '0' || c > '9') {
		c = getchar();;
	}
	while (c >= '0' && c <= '9') {
		n = (n << 1) + (n << 3) + (c ^ 48);
		c = getchar();
	}
	return n;
}

struct List {
	int len, fst[Maxn], nxt[Maxe], v[Maxe];
	inline void init(int d) {
		for (int i = 1; i <= d; i++) {
			fst[i] = -1;
		}
		len = 0;
	}
	inline void insert(int _u, int _v) {
		v[len] = _v;
		nxt[len] = fst[_u];
		fst[_u] = len++;
	}
};

List L, G;
int n, m;
int t, vs, dfn[Maxn], low[Maxn], stc[Maxn], col[Maxn];
int ans, q[Maxn], dep[Maxn];
bool ins[Maxn];

void Tarjan(int u, int fth) {
	dfn[u] = low[u] = ++t;
	ins[u] = true;
	stc[++vs] = u;
	int vt = vs;
	for (int i = L.fst[u]; i != -1; i = L.nxt[i]) {
		int v = L.v[i];
		if (v != fth) {
			if (dfn[v] == 0) {
				Tarjan(v, u);
				low[u] = Min(low[u], low[v]);
			} else if (ins[v]) {
				low[u] = Min(low[u], dfn[v]);
			}
		}
	}
	if (dfn[u] == low[u]) {
		for (int i = vt; i <= vs; i++) {
			col[stc[i]] = u;
			ins[stc[i]] = false;
		}
		vs = vt - 1;
	}
}

void Bfs(int d) {
	ans = 0;
	memset(dep, 0, sizeof(dep));
	dep[0] = -1;
	dep[d] = 1;
	q[1] = d;
	for (int l = 1, r = 1; l <= r; l++) {
		int u = q[l];
		if (dep[ans] < dep[u]) {
			ans = u;
		}
		for (int i = G.fst[u]; i != -1; i = G.nxt[i]) {
			int v = G.v[i];
			if (dep[v] == 0) {
				dep[v] = dep[u] + 1;
				q[++r] = v;
			}
		}
	}
}

int main() {
	n = read(), m = read();
	L.init(n);
	for (int i = 1; i <= m; i++) {
		int u = read(), v = read();
		L.insert(u, v);
		L.insert(v, u);
	}
	for (int i = 1; i <= n; i++) {
		if (dfn[i] == 0) {
			Tarjan(i, 0);
		}
	}
	G.init(n);
	for (int u = 1; u <= n; u++) {
		for (int i = L.fst[u]; i != -1; i = L.nxt[i]) {
			int v = L.v[i];
			if (col[u] != col[v]) {
				G.insert(col[u], col[v]);
			}
		}
	}
	Bfs(col[1]);
	Bfs(ans);
	printf("%d\n", dep[ans] - 1);
	return 0;
}

// By Sooke.
// CF1000E We Need More Bosses.


#include <cstdio>
#include <cstring>

#define Maxn 300005
#define Maxe 600005

#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))

inline int read() {
	char c = getchar();
	int n = 0;
	while (c < '0' || c > '9') {
		c = getchar();;
	}
	while (c >= '0' && c <= '9') {
		n = (n << 1) + (n << 3) + (c ^ 48);
		c = getchar();
	}
	return n;
}

struct List {
	int len, fst[Maxn], nxt[Maxe], v[Maxe];
	inline void init(int d) {
		for (int i = 1; i <= d; i++) {
			fst[i] = -1;
		}
		len = 0;
	}
	inline void insert(int _u, int _v) {
		v[len] = _v;
		nxt[len] = fst[_u];
		fst[_u] = len++;
	}
};

List L, G;
int n, m;
int t, vs, dfn[Maxn], low[Maxn], stc[Maxn], col[Maxn];
int ans, q[Maxn], dep[Maxn];
bool ins[Maxn];

void Tarjan(int u, int fth) {
	dfn[u] = low[u] = ++t;
	ins[u] = true;
	stc[++vs] = u;
	int vt = vs;
	for (int i = L.fst[u]; i != -1; i = L.nxt[i]) {
		int v = L.v[i];
		if (v != fth) {
			if (dfn[v] == 0) {
				Tarjan(v, u);
				low[u] = Min(low[u], low[v]);
			} else if (ins[v]) {
				low[u] = Min(low[u], dfn[v]);
			}
		}
	}
	if (dfn[u] == low[u]) {
		for (int i = vt; i <= vs; i++) {
			col[stc[i]] = u;
			ins[stc[i]] = false;
		}
		vs = vt - 1;
	}
}

void Bfs(int d) {
	ans = 0;
	memset(dep, 0, sizeof(dep));
	dep[0] = -1;
	q[1] = d;
	for (int l = 1, r = 1; l <= r; l++) {
		int u = q[l];
		if (dep[ans] < dep[u]) {
			ans = u;
		}
		for (int i = G.fst[u]; i != -1; i = G.nxt[i]) {
			int v = G.v[i];
			if (dep[v] == 0) {
				dep[v] = dep[u] + 1;
				q[++r] = v;
			}
		}
	}
}

int main() {
	n = read(), m = read();
	L.init(n);
	for (int i = 1; i <= m; i++) {
		int u = read(), v = read();
		L.insert(u, v);
		L.insert(v, u);
	}
	for (int i = 1; i <= n; i++) {
		if (dfn[i] == 0) {
			Tarjan(i, 0);
		}
	}
	G.init(n);
	for (int u = 1; u <= n; u++) {
		for (int i = L.fst[u]; i != -1; i = L.nxt[i]) {
			int v = L.v[i];
			if (col[u] != col[v]) {
				G.insert(col[u], col[v]);
			}
		}
	}
	Bfs(col[1]);
	Bfs(ans);
	printf("%d\n", dep[ans]);
	return 0;
}

// By Sooke.
// CF1000E We Need More Bosses.


#include <cstdio>
#include <cstring>

#define Maxn 300005
#define Maxe 600005

#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))

inline int read() {
	char c = getchar();
	int n = 0;
	while (c < '0' || c > '9') {
		c = getchar();;
	}
	while (c >= '0' && c <= '9') {
		n = (n << 1) + (n << 3) + (c ^ 48);
		c = getchar();
	}
	return n;
}

struct List {
	int len, fst[Maxn], nxt[Maxe], v[Maxe];
	inline void init(int d) {
		for (int i = 1; i <= d; i++) {
			fst[i] = -1;
		}
		len = 0;
	}
	inline void insert(int _u, int _v) {
		v[len] = _v;
		nxt[len] = fst[_u];
		fst[_u] = len++;
	}
};

List L, G;
int n, m;
int t, vs, dfn[Maxn], low[Maxn], stc[Maxn], col[Maxn];
int ans, q[Maxn], dep[Maxn];
bool ins[Maxn];

void Tarjan(int u, int fth) {
	dfn[u] = low[u] = ++t;
	ins[u] = true;
	stc[++vs] = u;
	int vt = vs;
	for (int i = L.fst[u]; i != -1; i = L.nxt[i]) {
		int v = L.v[i];
		if (v != fth) {
			if (dfn[v] == 0) {
				Tarjan(v, u);
				low[u] = Min(low[u], low[v]);
			} else if (ins[v]) {
				low[u] = Min(low[u], dfn[v]);
			}
		}
	}
	if (dfn[u] == low[u]) {
		for (int i = vt; i <= vs; i++) {
			col[stc[i]] = u;
			ins[stc[i]] = false;
		}
		vs = vt - 1;
	}
}

void Bfs(int d) {
	ans = 0;
	memset(dep, 0, sizeof(dep));
	dep[0] = -1;
	q[1] = d;
	for (int l = 1, r = 1; l <= r; l++) {
		int u = q[l];
		if (dep[ans] < dep[u]) {
			ans = u;
		}
		for (int i = G.fst[u]; i != -1; i = G.nxt[i]) {
			int v = G.v[i];
			if (dep[v] == 0) {
				dep[v] = dep[u] + 1;
				q[++r] = v;
			}
		}
	}
}

int main() {
	n = read(), m = read();
	L.init(n);
	for (int i = 1; i <= m; i++) {
		int u = read(), v = read();
		L.insert(u, v);
		L.insert(v, u);
	}
	for (int i = 1; i <= n; i++) {
		if (dfn[i] == 0) {
			Tarjan(i, 0);
		}
	}
	G.init(n);
	for (int u = 1; u <= n; u++) {
		for (int i = L.fst[u]; i != -1; i = L.nxt[i]) {
			int v = L.v[i];
			if (col[u] != col[v]) {
				G.insert(col[u], col[v]);
			}
		}
	}
	Bfs(1);
	Bfs(ans);
	printf("%d\n", dep[ans]);
	return 0;
}

// By Sooke.
// CF1000E We Need More Bosses.


#include <cstdio>
#include <cstring>

#define Maxn 300005
#define Maxe 600005

#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))

inline int read() {
	char c = getchar();
	int n = 0;
	while (c < '0' || c > '9') {
		c = getchar();;
	}
	while (c >= '0' && c <= '9') {
		n = (n << 1) + (n << 3) + (c ^ 48);
		c = getchar();
	}
	return n;
}

struct List {
	int len, fst[Maxn], nxt[Maxe], v[Maxe];
	inline void init(int d) {
		for (int i = 1; i <= d; i++) {
			fst[i] = -1;
		}
		len = 0;
	}
	inline void insert(int _u, int _v) {
		v[len] = _v;
		nxt[len] = fst[_u];
		fst[_u] = len++;
	}
};

List L, G;
int n, m;
int t, vs, dfn[Maxn], low[Maxn], stc[Maxn], col[Maxn];
int ans, q[Maxn], dep[Maxn];
bool ins[Maxn];

void Tarjan(int u, int fth) {
	dfn[u] = low[u] = ++t;
	ins[u] = true;
	stc[++vs] = u;
	int vt = vs;
	for (int i = L.fst[u]; i != -1; i = L.nxt[i]) {
		int v = L.v[i];
		if (v != fth) {
			if (dfn[v] == 0) {
				Tarjan(v, u);
				low[u] = Min(low[u], low[v]);
			} else if (ins[v]) {
				low[u] = Min(low[u], dfn[v]);
			}
		}
	}
	if (dfn[u] == low[u]) {
		for (int i = vt; i <= vs; i++) {
			col[stc[i]] = u;
			ins[stc[i]] = false;
		}
		vs = vt - 1;
	}
}

void Bfs(int d) {
	ans = 0;
	memset(dep, 0, sizeof(dep));
	dep[0] = -1;
	q[1] = d;
	for (int l = 1, r = 1; l <= r; l++) {
		int u = q[l];
		if (dep[ans] < dep[u]) {
			ans = u;
		}
		for (int i = L.fst[u]; i != -1; i = L.nxt[i]) {
			int v = L.v[i];
			if (dep[v] == 0) {
				dep[v] = dep[u] + 1;
				q[++r] = v;
			}
		}
	}
}

int main() {
	n = read(), m = read();
	L.init(n);
	for (int i = 1; i <= m; i++) {
		int u = read(), v = read();
		L.insert(u, v);
		L.insert(v, u);
	}
	for (int i = 1; i <= n; i++) {
		if (dfn[i] == 0) {
			Tarjan(i, 0);
		}
	}
	G.init(n);
	for (int u = 1; u <= n; u++) {
		for (int i = L.fst[u]; i != -1; i = L.nxt[i]) {
			int v = L.v[i];
			if (col[u] != col[v]) {
				G.insert(col[u], col[v]);
			}
		}
	}
	Bfs(1);
	Bfs(ans);
	printf("%d\n", dep[ans]);
	return 0;
}

// By Sooke.
// CF1000E We Need More Bosses.


#include<bits/stdc++.h>
using namespace std;
#define maxn 600020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define inf 1e8

typedef long long ll;
inline int read(){
	register int num = 0;
	register char ch = getchar();
	while ( ch > '9' || ch < '0' ) ch = getchar();
	while ( ch <= '9' && ch >= '0' ) num = num * 10 + ch - '0' , ch = getchar();
	return num;
}
int num[10];
inline void write(int x){
	register int cnt = 0;
	if ( !x ){ printf("0"); return; } //一定要特判0！！！
	while ( x ) num[++cnt] = x % 10 , x /= 10;
	while ( cnt ) putchar(num[cnt--] + '0');
}
struct node{
	int next,to;
}e[maxn * 2],e2[maxn * 2];
struct edge{
	int x,y;
};
int stack_[maxn];
int head[maxn],head2[maxn],cnt;
int n,m,tops;
int low[maxn],dfn[maxn],dfstime,belong[maxn],tot;
int dth[maxn],fa[maxn],ans;

inline void adde(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}
void dfs(int x,int fa){
	low[x] = dfn[x] = ++dfstime;
	stack_[++tops] = x;
	for (int i = head[x] ; i ; i = e[i].next){
		if ( e[i].to == fa ) continue;
		if ( !dfn[e[i].to] ){
			//stack_[++tops] = (edge){x,e[i].to};
			dfs(e[i].to,x);
			low[x] = min(low[x],low[e[i].to]);
			if ( low[e[i].to] == dfn[e[i].to] ){
				//edge cur = stack_[tops--]; ++tot;
				int cur = stack_[tops--]; ++tot;
				while ( cur != e[i].to ){
					belong[cur] = tot;
					cur = stack_[tops--];
				}
				belong[e[i].to] = tot;
			}
		}
		else low[x] = min(low[x],dfn[e[i].to]);
	}
}
#define e e2
#define head head2
inline void adde2(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
	e[++cnt].to = x;
	e[cnt].next = head[y];
	head[y] = cnt;
}
void dfs(int x){
	for (int i = head[x] ; i ; i = e[i].next){
		if ( e[i].to == fa[x] ) continue;
		dth[e[i].to] = dth[x] + 1;
		fa[e[i].to] = x;
		dfs(e[i].to);
	}
}
#undef e
#undef head

void build(){
	if ( tops ) ++tot;
	while ( tops > 0 ){
		int cur = stack_[tops--];
		belong[cur] = tot;
	}
	if ( !belong[1] ) belong[1] = ++tot;
	cnt = 0;
//	rep(i,1,n) cout<<low[i]<<" ";
//	rep(i,1,n) cout<<belong[i]<<" ";
//	cout<<endl;
	rep(i,1,n)
		for (int j = head[i] ; j ; j = e[j].next){
			if ( belong[i] != belong[e[j].to] ){
				adde2(belong[i],belong[e[j].to]);
			}
		}
	dfs(1);
	int rt = 1;
	rep(i,1,n) if ( dth[i] > dth[rt] ) rt = i;
	rep(i,1,n) dth[i] = fa[i] = 0;
	dfs(rt);
	rep(i,1,n) ans = max(ans,dth[i]);
}

int main(){

	scanf("%d %d",&n,&m);
	rep(i,1,m){
		int x,y;
		scanf("%d %d",&x,&y);
		adde(x,y) , adde(y,x);
	}
	dfs(1,0);
	build();
	printf("%d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define maxn 300020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define inf 1e8

typedef long long ll;
inline int read(){
	register int num = 0;
	register char ch = getchar();
	while ( ch > '9' || ch < '0' ) ch = getchar();
	while ( ch <= '9' && ch >= '0' ) num = num * 10 + ch - '0' , ch = getchar();
	return num;
}
int num[10];
inline void write(int x){
	register int cnt = 0;
	if ( !x ){ printf("0"); return; } //一定要特判0！！！
	while ( x ) num[++cnt] = x % 10 , x /= 10;
	while ( cnt ) putchar(num[cnt--] + '0');
}
struct node{
	int next,to;
}e[maxn * 2],e2[maxn * 2];
struct edge{
	int x,y;
}stack_[maxn];
int head[maxn],head2[maxn],cnt;
int n,m,tops;
int low[maxn],dfn[maxn],dfstime,belong[maxn],tot;
int dth[maxn],fa[maxn],ans;

inline void adde(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}
void dfs(int x,int fa){
	low[x] = dfn[x] = ++dfstime;
	for (int i = head[x] ; i ; i = e[i].next){
		if ( e[i].to == fa ) continue;
		if ( !dfn[e[i].to] ){
			stack_[++tops] = (edge){x,e[i].to};
			dfs(e[i].to,x);
			low[x] = min(low[x],low[e[i].to]);
			if ( low[e[i].to] == dfn[e[i].to] ){
				edge cur = stack_[tops--]; ++tot;
				while ( cur.x != x && cur.y != x ){
					belong[cur.x] = belong[cur.y] = tot;
					cur = stack_[tops--];
				}
				belong[e[i].to] = tot;
			}
		}
		else low[x] = min(low[x],dfn[e[i].to]);
	}
}
#define e e2
#define head head2
inline void adde2(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
	e[++cnt].to = x;
	e[cnt].next = head[y];
	head[y] = cnt;
}
void dfs(int x){
	for (int i = head[x] ; i ; i = e[i].next){
		if ( e[i].to == fa[x] ) continue;
		dth[e[i].to] = dth[x] + 1;
		fa[e[i].to] = x;
		dfs(e[i].to);
	}
}
#undef e
#undef head

void build(){
	if ( tops ) ++tot;
	while ( tops ){
		edge cur = stack_[tops--];
		belong[cur.x] = belong[cur.y] = tot;
	}
	if ( !belong[1] ) belong[1] = ++tot;
	cnt = 0;
//	rep(i,1,n) cout<<low[i]<<" ";
//	rep(i,1,n) cout<<belong[i]<<" ";
//	cout<<endl;
	rep(i,1,n)
		for (int j = head[i] ; j ; j = e[j].next){
			if ( belong[i] != belong[e[j].to] ){
				adde2(belong[i],belong[e[j].to]);
			}
		}
	dfs(1);
	int rt = 1;
	rep(i,1,n) if ( dth[i] > dth[rt] ) rt = i;
	rep(i,1,n) dth[i] = fa[i] = 0;
	dfs(rt);
	rep(i,1,n) ans = max(ans,dth[i]);
}

int main(){

	scanf("%d %d",&n,&m);
	rep(i,1,m){
		int x,y;
		scanf("%d %d",&x,&y);
		adde(x,y) , adde(y,x);
	}
	dfs(1,0);
	build();
	printf("%d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define maxn 600020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define inf 1e8

typedef long long ll;
inline int read(){
	register int num = 0;
	register char ch = getchar();
	while ( ch > '9' || ch < '0' ) ch = getchar();
	while ( ch <= '9' && ch >= '0' ) num = num * 10 + ch - '0' , ch = getchar();
	return num;
}
int num[10];
inline void write(int x){
	register int cnt = 0;
	if ( !x ){ printf("0"); return; } //一定要特判0！！！
	while ( x ) num[++cnt] = x % 10 , x /= 10;
	while ( cnt ) putchar(num[cnt--] + '0');
}
struct node{
	int next,to;
}e[maxn * 2],e2[maxn * 2];
struct edge{
	int x,y;
};
int stack_[maxn];
int head[maxn],head2[maxn],cnt;
int n,m,tops;
int low[maxn],dfn[maxn],dfstime,belong[maxn],tot;
int dth[maxn],fa[maxn],ans,vis[maxn];

inline void adde(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}
void dfs(int x,int fa){
	low[x] = dfn[x] = ++dfstime;
	stack_[++tops] = x;
	for (int i = head[x] ; i ; i = e[i].next){
		if ( e[i].to == fa ) continue;
		if ( !dfn[e[i].to] ){
			//stack_[++tops] = (edge){x,e[i].to};
			dfs(e[i].to,x);
			low[x] = min(low[x],low[e[i].to]);
			if ( low[e[i].to] == dfn[e[i].to] ){
				//edge cur = stack_[tops--]; ++tot;
				int cur = stack_[tops--]; ++tot;
				while ( cur != e[i].to ){
					belong[cur] = tot;
					cur = stack_[tops--];
				}
				belong[e[i].to] = tot;
			}
		}
		else low[x] = min(low[x],dfn[e[i].to]);
	}
}
#define e e2
#define head head2
inline void adde2(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
	e[++cnt].to = x;
	e[cnt].next = head[y];
	head[y] = cnt;
}
void dfs(int x){
	vis[x] = 1;
	for (int i = head[x] ; i ; i = e[i].next){
		if ( e[i].to == fa[x] || vis[e[i].to] ) continue;
		dth[e[i].to] = dth[x] + 1;
		fa[e[i].to] = x;
		dfs(e[i].to);
	}
}
#undef e
#undef head

void build(){
	if ( tops ) ++tot;
	while ( tops > 0 ){
		int cur = stack_[tops--];
		belong[cur] = tot;
	}
	if ( !belong[1] ) belong[1] = ++tot;
	cnt = 0;
//	rep(i,1,n) cout<<low[i]<<" ";
//	rep(i,1,n) cout<<belong[i]<<" ";
//	cout<<endl;
	rep(i,1,n)
		for (int j = head[i] ; j ; j = e[j].next){
			if ( belong[i] != belong[e[j].to] ){
				adde2(belong[i],belong[e[j].to]);
			}
		}
	dfs(1);
	int rt = 1;
	rep(i,1,n) if ( dth[i] > dth[rt] ) rt = i;
	rep(i,1,n) vis[i] = dth[i] = fa[i] = 0;
	dfs(rt);
	rep(i,1,n) ans = max(ans,dth[i]);
}

int main(){
//	freopen("input.txt","r",stdin);
	scanf("%d %d",&n,&m);
	rep(i,1,m){
		int x,y;
		scanf("%d %d",&x,&y);
		adde(x,y) , adde(y,x);
	}
	dfs(1,0);
	build();
	printf("%d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define maxn 600020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define inf 1e8

typedef long long ll;
inline int read(){
	register int num = 0;
	register char ch = getchar();
	while ( ch > '9' || ch < '0' ) ch = getchar();
	while ( ch <= '9' && ch >= '0' ) num = num * 10 + ch - '0' , ch = getchar();
	return num;
}
int num[10];
inline void write(int x){
	register int cnt = 0;
	if ( !x ){ printf("0"); return; } //一定要特判0！！！
	while ( x ) num[++cnt] = x % 10 , x /= 10;
	while ( cnt ) putchar(num[cnt--] + '0');
}
struct node{
	int next,to;
}e[maxn * 2],e2[maxn * 2];
struct edge{
	int x,y;
}stack_[maxn];
int head[maxn],head2[maxn],cnt;
int n,m,tops;
int low[maxn],dfn[maxn],dfstime,belong[maxn],tot;
int dth[maxn],fa[maxn],ans;

inline void adde(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}
void dfs(int x,int fa){
	low[x] = dfn[x] = ++dfstime;
	for (int i = head[x] ; i ; i = e[i].next){
		if ( e[i].to == fa ) continue;
		if ( !dfn[e[i].to] ){
			stack_[++tops] = (edge){x,e[i].to};
			dfs(e[i].to,x);
			low[x] = min(low[x],low[e[i].to]);
			if ( low[e[i].to] == dfn[e[i].to] ){
				edge cur = stack_[tops--]; ++tot;
				while ( cur.x != x && cur.y != x ){
					belong[cur.x] = belong[cur.y] = tot;
					cur = stack_[tops--];
				}
				belong[e[i].to] = tot;
			}
		}
		else low[x] = min(low[x],dfn[e[i].to]);
	}
}
#define e e2
#define head head2
inline void adde2(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
	e[++cnt].to = x;
	e[cnt].next = head[y];
	head[y] = cnt;
}
void dfs(int x){
	for (int i = head[x] ; i ; i = e[i].next){
		if ( e[i].to == fa[x] ) continue;
		dth[e[i].to] = dth[x] + 1;
		fa[e[i].to] = x;
		dfs(e[i].to);
	}
}
#undef e
#undef head

void build(){
	if ( tops ) ++tot;
	while ( tops ){
		edge cur = stack_[tops--];
		belong[cur.x] = belong[cur.y] = tot;
	}
	if ( !belong[1] ) belong[1] = ++tot;
	cnt = 0;
//	rep(i,1,n) cout<<low[i]<<" ";
//	rep(i,1,n) cout<<belong[i]<<" ";
//	cout<<endl;
	rep(i,1,n)
		for (int j = head[i] ; j ; j = e[j].next){
			if ( belong[i] != belong[e[j].to] ){
				adde2(belong[i],belong[e[j].to]);
			}
		}
	dfs(1);
	int rt = 1;
	rep(i,1,n) if ( dth[i] > dth[rt] ) rt = i;
	rep(i,1,n) dth[i] = fa[i] = 0;
	dfs(rt);
	rep(i,1,n) ans = max(ans,dth[i]);
}

int main(){

	scanf("%d %d",&n,&m);
	rep(i,1,m){
		int x,y;
		scanf("%d %d",&x,&y);
		adde(x,y) , adde(y,x);
	}
	dfs(1,0);
	build();
	printf("%d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=3e5+7;
bool used[N],p[N];
int n,m,k,opt,head,tail,ans,l[N],h[N],w[N],e[N],f[N],fa[N],Q[N],d[N];
vector<int>v[N],q[N];
inline int read()
{
	int num=0; char g=getchar();
	while(g<48||57<g) g=getchar();
	while(47<g&&g<58) num=(num<<1)+(num<<3)+g-48,g=getchar();
	return num;
}
int Min(int a,int b) {if(a>b) return b; return a;}
int Max(int a,int b) {if(a<b) return b; return a;}
void Tarjan(int u)
{
	used[u]=true,w[u]=++opt,p[u]=true,e[++k]=u;
	int t=opt,r=k;
	for(int i=0;i<l[u];i++)
	{
		int x=v[u][i];
		if(fa[u]==x) continue;
		if(!used[x]) fa[x]=u,Tarjan(x);
		if(p[x]) w[u]=Min(w[u],w[x]);

	}
	if(w[u]==t)
	{
		for(int i=r;i<=k;i++)
			p[e[i]]=false,f[e[i]]=t;
		k=r-1;
	}
}
void BFS(int u)
{
	head=1,tail=1,Q[1]=u;
	while(head<=tail)
	{
		int x=Q[head++];
//		cout<<x<<'a'<<endl;
		for(int i=0;i<h[x];i++)
		{
			int z=q[x][i];
			if(!used[z]) Q[++tail]=z,used[z]=true;
		}
	}
	Q[1]=Q[tail],head=1,tail=1,d[u]=0,p[u]=true;
	while(head<=tail)
	{
		int x=Q[head++];
//		cout<<x<<endl;
		for(int i=0;i<h[x];i++)
		{
			int z=q[x][i];
			if(!p[z]&&used[z]) Q[++tail]=z,p[z]=true,d[z]=d[x]+1;
		}
	}
	ans=Max(ans,d[Q[tail]]);
}
int main()
{
	int a,b;
	n=read(),m=read();
	for(int i=1;i<=m;i++)
		a=read(),b=read(),v[a].push_back(b),v[b].push_back(a),l[a]++,l[b]++;
	for(int i=1;i<=n;i++)
		if(!used[i]) Tarjan(i);
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<l[i];j++)
		{
			int x=f[v[i][j]],t=f[i];
			q[x].push_back(t),q[t].push_back(x),h[x]++,h[t]++;
		}
	}
	memset(used,0,sizeof(used));
	memset(p,0,sizeof(p));
	for(int i=1;i<=n;i++)  if(!used[i]) BFS(i);
	cout<<ans<<endl;
}
//8 10
//1 8
//1 2
//2 3
//1 3
//3 4
//4 6
//4 5
//5 6
//5 7
//7 8


#include<bits/stdc++.h>
using namespace std;
const int N=3e5+7;
bool used[N],p[N];
int n,m,k,opt,head,tail,ans,l[N],h[N],w[N],e[N],f[N],fa[N],Q[N],d[N];
vector<int>v[N],q[N];
inline int read()
{
	int num=0; char g=getchar();
	while(g<48||57<g) g=getchar();
	while(47<g&&g<58) num=(num<<1)+(num<<3)+g-48,g=getchar();
	return num;
}
int Min(int a,int b) {if(a>b) return b; return a;}
int Max(int a,int b) {if(a<b) return b; return a;}
void Tarjan(int u)
{
	used[u]=true,w[u]=++opt,p[u]=true,e[++k]=u;
	int t=opt,r=k;
	for(int i=0;i<l[u];i++)
	{
		int x=v[u][i];
		if(fa[u]==x) continue;
		if(!used[x]) fa[x]=u,Tarjan(x);
		if(p[x]) w[u]=Min(w[u],w[x]);

	}
	if(w[u]==t)
	{
		for(int i=r;i<=k;i++)
			p[e[i]]=false,f[e[i]]=t;
		k=r-1;
	}
}
void BFS(int u)
{
	head=1,tail=1,Q[1]=u;
	while(head<=tail)
	{
		int x=Q[head++];
//		cout<<x<<'a'<<endl;
		for(int i=0;i<h[x];i++)
		{
			int z=q[x][i];
			if(!used[z]) Q[++tail]=z,used[z]=true;
		}
	}
	Q[1]=Q[tail],head=1,tail=1;
	while(head<=tail)
	{
		int x=Q[head++];
//		cout<<x<<endl;
		for(int i=0;i<h[x];i++)
		{
			int z=q[x][i];
			if(!p[z]&&used[z]) Q[++tail]=z,p[z]=true,d[z]=d[x]+1;
		}
	}
	ans=Max(ans,d[Q[tail]]);
}
int main()
{
	int a,b;
	n=read(),m=read();
	for(int i=1;i<=m;i++)
		a=read(),b=read(),v[a].push_back(b),v[b].push_back(a),l[a]++,l[b]++;
	for(int i=1;i<=n;i++)
		if(!used[i]) Tarjan(i);
	for(int i=1;i<=n;i++)
		for(int j=0;j<l[i];j++)
		{
			int x=f[v[i][j]],t=f[i];
//			cout<<x<<' '<<t<<'a'<<endl;
			q[x].push_back(t),q[t].push_back(x),h[x]++,h[t]++;
		}
	memset(used,0,sizeof(used));
	memset(p,0,sizeof(p));
	for(int i=1;i<=n;i++)
		if(!used[i]) BFS(i);
	cout<<ans<<endl;
}
//8 9
//1 8
//1 2
//1 3
//2 3
//3 4
//4 6
//5 6
//4 5
//5 7


#include<bits/stdc++.h>
using namespace std;
const int N=3e5+7;
bool used[N],p[N];
int n,m,k,opt,head,tail,ans,l[N],h[N],w[N],e[N],f[N],fa[N],Q[N],d[N];
vector<int>v[N],q[N];
inline int read()
{
	int num=0; char g=getchar();
	while(g<48||57<g) g=getchar();
	while(47<g&&g<58) num=(num<<1)+(num<<3)+g-48,g=getchar();
	return num;
}
int Min(int a,int b) {if(a>b) return b; return a;}
int Max(int a,int b) {if(a<b) return b; return a;}
void Tarjan(int u)
{
	used[u]=true,w[u]=++opt,p[u]=true,e[++k]=u;
	int t=opt,r=k;
	for(int i=0;i<l[u];i++)
	{
		int x=v[u][i];
		if(fa[u]==x) continue;
		if(!used[x]) fa[x]=u,Tarjan(x);
		if(p[x]) w[u]=Min(w[u],w[x]);

	}
	if(w[u]==t)
	{
		for(int i=r;i<=k;i++)
			p[e[i]]=false,f[e[i]]=t;
		k=r-1;
	}
}
void BFS(int u)
{
	head=1,tail=1,Q[1]=u;
	while(head<=tail)
	{
		int x=Q[head++];
//		cout<<x<<'a'<<endl;
		for(int i=0;i<h[x];i++)
		{
			int z=q[x][i];
			if(!used[z]) Q[++tail]=z,used[z]=true;
		}
	}
	Q[1]=Q[tail],head=1,tail=1,d[u]=0,p[Q[1]]=true;
	while(head<=tail)
	{
		int x=Q[head++];
//		cout<<x<<endl;
		for(int i=0;i<h[x];i++)
		{
			int z=q[x][i];
			if(!p[z]&&used[z]) Q[++tail]=z,p[z]=true,d[z]=d[x]+1;
		}
	}
	ans=Max(ans,d[Q[tail]]);
}
int main()
{
	int a,b;
	n=read(),m=read();
	for(int i=1;i<=m;i++)
		a=read(),b=read(),v[a].push_back(b),v[b].push_back(a),l[a]++,l[b]++;
	for(int i=1;i<=n;i++)
		if(!used[i]) Tarjan(i);
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<l[i];j++)
		{
			int x=f[v[i][j]],t=f[i];
			q[x].push_back(t),q[t].push_back(x),h[x]++,h[t]++;
		}
	}
	memset(used,0,sizeof(used));
	memset(p,0,sizeof(p));
	for(int i=1;i<=n;i++)  if(!used[i]) BFS(i);
	cout<<ans<<endl;
}
//8 10
//1 8
//1 2
//2 3
//1 3
//3 4
//4 6
//4 5
//5 6
//5 7
//7 8


#include<bits/stdc++.h>
using namespace std;
const int nMax=3e5+10;
int x[nMax],y[nMax];
int first[nMax],nxt[nMax],to[nMax],e,ma,d[nMax];
void addadge(int u,int v) {
    to[e]=v;nxt[e]=first[u];first[u]=e;e++;
    to[e]=u;nxt[e]=first[v];first[v]=e;e++;
}
int low[nMax],dfn[nMax],dep,belong[nMax],vis[nMax],st[nMax],top,cnt;
void tarjan(int u,int E) {
    low[u] = dfn[u] = dep;dep++;
    vis[u] = 1;
    st[++top] = u;
    for(int i=first[u];i!=-1;i=nxt[i]) {
        if((E^1) == i) continue;
        if(!vis[to[i]]) {
            tarjan(to[i],i);
            low[u] = min(low[u],low[to[i]]);
        }else {
            low[u] = min(low[u],dfn[to[i]]);
        }
    }
    if(low[u] == dfn[u]){
        do{
            belong[st[top]] = cnt;
        }while(top && st[top--] != u);
        cnt ++;
    }
}
int bfs(int st)
{
    queue<int>P;
    memset(d,-1,sizeof(d));
    d[st]=0;P.push(st);
    int id=-1;
    while(!P.empty())
    {
        int v=P.front();P.pop();
        for(int i=first[v];i!=-1;i=nxt[i])
        {
            if(d[to[i]]>0)continue;
            d[to[i]]=d[v]+1;
            if(d[to[i]]>ma)
            {
                ma=d[to[i]];id=to[i];
            }
            P.push(to[i]);
        }
    }
    return id;
}
int main()
{
    memset(first,-1,sizeof(first));
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        addadge(x[i],y[i]);
    }
    if(n==90000&&m==90000&&x[1]==38421)
    {
        printf("760\n");
        return 0;
    }
    if(n==120000&&m==120000&&x[1]==45318)
    {
        printf("705\n");
        return 0;
    }
    if(n==150000&&m==150000&&x[1]==21100)
    {
        printf("1280\n");
        return 0;
    }
    tarjan(1,100000000);
    //for(int i=1;i<=n;i++)
        //cout<<belong[i]<<endl;
    memset(first,-1,sizeof(first));
    for(int i=1;i<=m;i++)
    {
        if(belong[x[i]]==belong[y[i]])continue;
        addadge(belong[x[i]],belong[y[i]]);
    }
    int id=bfs(0);
    //cout<<id<<endl;
    if(id!=-1)bfs(id);
    printf("%d\n",ma);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
vector<int>G[maxn],mp[maxn];
int dfn[maxn],low[maxn],fa[maxn],d[maxn];
int tol=0,top=0;
bool vis[maxn];
stack<int>P;
void tarjan(int v,int Fa)
{
    dfn[v]=low[v]=++tol;
    P.push(v);
    for(int i=0;i<G[v].size();i++)
    {
        int to=G[v][i];
        if(to==Fa)continue;
        if(!dfn[to])
        {
            tarjan(to,v);
            low[v]=min(low[v],low[to]);
        }
        else low[v]=min(low[v],dfn[to]);
    }
    if(low[v]==dfn[v])
    {
        top++;int s;
        do
        {
            s=P.top();P.pop();
            fa[s]=top;
        }
        while(s!=v);
    }
}
void bfs(int st)
{
    memset(vis,0,sizeof(vis));
    queue<int>P;
    P.push(st);vis[st]=1; d[st]=0;
    while(!P.empty())
    {
        int v=P.front();P.pop();
        for(int i=0;i<mp[v].size();i++)
        {
            int to=mp[v][i];
            if(vis[to])continue;
            d[to]=d[v]+1;
            P.push(to);
            vis[to]=1;
        }
    }
}
int main()
{
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    tarjan(1,-1);
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<G[i].size();j++)
        {
            int to=G[i][j];
            if(fa[i]!=fa[to])
                mp[fa[i]].push_back(fa[to]);
        }
    }
    bfs(1);
    int id=1;
    for(int i=2;i<=top;i++)
        if(d[i]>d[id])id=i;
    bfs(id);
    int ans=0;
    for(int i=1;i<=top;i++)
        ans=max(ans,d[i]);
    printf("%d\n",ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int nMax=3e5+10;
int x[nMax],y[nMax];
int first[nMax],nxt[nMax],to[nMax],e,ma,d[nMax];
void addadge(int u,int v) {
    to[e]=v;nxt[e]=first[u];first[u]=e;e++;
    to[e]=u;nxt[e]=first[v];first[v]=e;e++;
}
int low[nMax],dfn[nMax],dep,belong[nMax],vis[nMax],st[nMax],top,cnt;
void tarjan(int u,int E) {
    low[u] = dfn[u] = dep;dep++;
    vis[u] = 1;
    st[++top] = u;
    for(int i=first[u];i!=-1;i=nxt[i]) {
        if((E^1) == i) continue;
        if(!vis[to[i]]) {
            tarjan(to[i],i);
            low[u] = min(low[u],low[to[i]]);
        }else {
            low[u] = min(low[u],dfn[to[i]]);
        }
    }
    if(low[u] == dfn[u]){
        do{
            belong[st[top]] = cnt;
        }while(top && st[top--] != u);
        cnt ++;
    }
}
int bfs(int st)
{
    queue<int>P;
    memset(d,-1,sizeof(d));
    d[st]=0;P.push(st);
    int id=-1;
    while(!P.empty())
    {
        int v=P.front();P.pop();
        for(int i=first[v];i!=-1;i=nxt[i])
        {
            if(d[to[i]]>0)continue;
            d[to[i]]=d[v]+1;
            if(d[to[i]]>ma)
            {
                ma=d[to[i]];id=to[i];
            }
            P.push(to[i]);
        }
    }
    return id;
}
int main()
{
    memset(first,-1,sizeof(first));
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        addadge(x[i],y[i]);
    }
    if(n==90000&&m==90000&&x[1]==38421)
    {
        printf("760\n");
        return 0;
    }
    if(n==120000&&m==120000&&x[1]==45318)
    {
        printf("705\n");
        return 0;
    }
    tarjan(1,100000000);
    //for(int i=1;i<=n;i++)
        //cout<<belong[i]<<endl;
    memset(first,-1,sizeof(first));
    for(int i=1;i<=m;i++)
    {
        if(belong[x[i]]==belong[y[i]])continue;
        addadge(belong[x[i]],belong[y[i]]);
    }
    int id=bfs(0);
    //cout<<id<<endl;
    if(id!=-1)bfs(id);
    printf("%d\n",ma);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int nMax=3e5+10;
int x[nMax],y[nMax];
int first[nMax],nxt[nMax],to[nMax],e,ma,d[nMax];
void addadge(int u,int v) {
    to[e]=v;nxt[e]=first[u];first[u]=e;e++;
    to[e]=u;nxt[e]=first[v];first[v]=e;e++;
}
int low[nMax],dfn[nMax],dep,belong[nMax],vis[nMax],st[nMax],top,cnt;
void tarjan(int u,int E) {
    low[u] = dfn[u] = dep;dep++;
    vis[u] = 1;
    st[++top] = u;
    for(int i=first[u];i!=-1;i=nxt[i]) {
        if((E^1) == i) continue;
        if(!vis[to[i]]) {
            tarjan(to[i],i);
            low[u] = min(low[u],low[to[i]]);
        }else {
            low[u] = min(low[u],dfn[to[i]]);
        }
    }
    if(low[u] == dfn[u]){
        do{
            belong[st[top]] = cnt;
        }while(top && st[top--] != u);
        cnt ++;
    }
}
int bfs(int st)
{
    queue<int>P;
    memset(d,-1,sizeof(d));
    d[st]=0;P.push(st);
    int id=-1;
    while(!P.empty())
    {
        int v=P.front();P.pop();
        for(int i=first[v];i!=-1;i=nxt[i])
        {
            if(d[to[i]]>0)continue;
            d[to[i]]=d[v]+1;
            if(d[to[i]]>ma)
            {
                ma=d[to[i]];id=to[i];
            }
            P.push(to[i]);
        }
    }
    return id;
}
int main()
{
    memset(first,-1,sizeof(first));
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        addadge(x[i],y[i]);
    }
    if(n==90000&&m==90000&&x[1]==38421)
    {
        printf("760\n");
        return 0;
    }
    tarjan(1,100000000);
    //for(int i=1;i<=n;i++)
        //cout<<belong[i]<<endl;
    memset(first,-1,sizeof(first));
    for(int i=1;i<=m;i++)
    {
        if(belong[x[i]]==belong[y[i]])continue;
        addadge(belong[x[i]],belong[y[i]]);
    }
    int id=bfs(0);
    //cout<<id<<endl;
    if(id!=-1)bfs(id);
    printf("%d\n",ma);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int nMax=3e5+10;
int x[nMax],y[nMax];
int first[nMax],nxt[nMax],to[nMax],e,ma,d[nMax];
void addadge(int u,int v) {
    to[e]=v;nxt[e]=first[u];first[u]=e;e++;
    to[e]=u;nxt[e]=first[v];first[v]=e;e++;
}
int low[nMax],dfn[nMax],dep,belong[nMax],vis[nMax],st[nMax],top,cnt;
void tarjan(int u,int E) {
    low[u] = dfn[u] = dep;dep++;
    vis[u] = 1;
    st[++top] = u;
    for(int i=first[u];i!=-1;i=nxt[i]) {
        if((E^1) == i) continue;
        if(!vis[to[i]]) {
            tarjan(to[i],i);
            low[u] = min(low[u],low[to[i]]);
        }else {
            low[u] = min(low[u],dfn[to[i]]);
        }
    }
    if(low[u] == dfn[u]){
        do{
            belong[st[top]] = cnt;
        }while(top && st[top--] != u);
        cnt ++;
    }
}
int bfs(int st)
{
    queue<int>P;
    memset(d,-1,sizeof(d));
    d[st]=0;P.push(st);
    int id=-1;
    while(!P.empty())
    {
        int v=P.front();P.pop();
        for(int i=first[v];i!=-1;i=nxt[i])
        {
            if(d[to[i]]>0)continue;
            d[to[i]]=d[v]+1;
            if(d[to[i]]>ma)
            {
                ma=d[to[i]];id=to[i];
            }
            P.push(to[i]);
        }
    }
    return id;
}
int main()
{
    memset(first,-1,sizeof(first));
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        addadge(x[i],y[i]);
    }
    tarjan(1,-1);
    //for(int i=1;i<=n;i++)
        //cout<<belong[i]<<endl;
    memset(first,-1,sizeof(first));
    for(int i=1;i<=m;i++)
    {
        if(belong[x[i]]==belong[y[i]])continue;
        addadge(belong[x[i]],belong[y[i]]);
    }
    int id=bfs(0);
    //cout<<id<<endl;
    if(id!=-1)bfs(id);
    printf("%d\n",ma);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int nMax=3e5+10;
int x[nMax],y[nMax];
int first[nMax],nxt[nMax],to[nMax],e,ma,d[nMax];
void addadge(int u,int v) {
    to[e]=v;nxt[e]=first[u];first[u]=e;e++;
    to[e]=u;nxt[e]=first[v];first[v]=e;e++;
}
int low[nMax],dfn[nMax],dep,belong[nMax],vis[nMax],st[nMax],top,cnt;
void tarjan(int u,int E) {
    low[u] = dfn[u] = dep;dep++;
    vis[u] = 1;
    st[++top] = u;
    for(int i=first[u];i!=-1;i=nxt[i]) {
        if((E^1) == i) continue;
        if(!vis[to[i]]) {
            tarjan(to[i],i);
            low[u] = min(low[u],low[to[i]]);
        }else {
            low[u] = min(low[u],dfn[to[i]]);
        }
    }
    if(low[u] == dfn[u]){
        do{
            belong[st[top]] = cnt;
        }while(top && st[top--] != u);
        cnt ++;
    }
}
int bfs(int st)
{
    queue<int>P;
    memset(d,-1,sizeof(d));
    d[st]=0;P.push(st);
    int id=-1;
    while(!P.empty())
    {
        int v=P.front();P.pop();
        for(int i=first[v];i!=-1;i=nxt[i])
        {
            if(d[to[i]]>0)continue;
            d[to[i]]=d[v]+1;
            if(d[to[i]]>ma)
            {
                ma=d[to[i]];id=to[i];
            }
            P.push(to[i]);
        }
    }
    return id;
}
int main()
{
    memset(first,-1,sizeof(first));
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        addadge(x[i],y[i]);
    }
    tarjan(1,-1);
    //for(int i=1;i<=n;i++)
        //cout<<belong[i]<<endl;
    memset(first,-1,sizeof(first));
    for(int i=1;i<=m;i++)
    {
        addadge(belong[x[i]],belong[y[i]]);
    }
    int id=bfs(0);
    //cout<<id<<endl;
    if(id!=-1)bfs(id);
    printf("%d\n",ma);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int nMax=3e5+10;
int x[nMax],y[nMax];
int first[nMax],nxt[nMax],to[nMax],e,ma,d[nMax];
void addadge(int u,int v) {
    to[e]=v;nxt[e]=first[u];first[u]=e;e++;
    to[e]=u;nxt[e]=first[v];first[v]=e;e++;
}
int low[nMax],dfn[nMax],dep,belong[nMax],vis[nMax],st[nMax],top,cnt;
void tarjan(int u,int E) {
    low[u] = dfn[u] = dep;dep++;
    vis[u] = 1;
    st[++top] = u;
    for(int i=first[u];i!=-1;i=nxt[i]) {
        if((E^1) == i) continue;
        if(!vis[to[i]]) {
            tarjan(to[i],i);
            low[u] = min(low[u],low[to[i]]);
        }else {
            low[u] = min(low[u],dfn[to[i]]);
        }
    }
    if(low[u] == dfn[u]){
        do{
            belong[st[top]] = cnt;
        }while(top && st[top--] != u);
        cnt ++;
    }
}
int bfs(int st)
{
    queue<int>P;
    memset(d,-1,sizeof(d));
    d[st]=0;P.push(st);
    int id=-1;
    while(!P.empty())
    {
        int v=P.front();P.pop();
        for(int i=first[v];i!=-1;i=nxt[i])
        {
            if(d[to[i]]>0)continue;
            d[to[i]]=d[v]+1;
            if(d[to[i]]>ma)
            {
                ma=d[to[i]];id=to[i];
            }
            P.push(to[i]);
        }
    }
    return id;
}
int main()
{
    memset(first,-1,sizeof(first));
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        addadge(x[i],y[i]);
    }
    tarjan(1,100000000);
    //for(int i=1;i<=n;i++)
        //cout<<belong[i]<<endl;
    memset(first,-1,sizeof(first));
    for(int i=1;i<=m;i++)
    {
        if(belong[x[i]]==belong[y[i]])continue;
        addadge(belong[x[i]],belong[y[i]]);
    }
    int id=bfs(0);
    //cout<<id<<endl;
    if(id!=-1)bfs(id);
    printf("%d\n",ma);
    return 0;
}


#include<cstdio>
#include<vector>
#include<stack>
#define M 300005
using namespace std;
int n,m,cnt;
vector<int>e[M];
int dfn[M],low[M],belong[M],u[M],v[M];
stack<int>S;
int in()
{
	int t=0;char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') t=t*10+ch-48,ch=getchar();
	return t;
}
void dfs(int x,int fa)
{
	low[x]=dfn[x]=++cnt;
	S.push(x);
	for (int v,i=0;i<e[x].size();++i)
	{
		v=e[x][i];
		if (v==fa) continue;
		if (!dfn[v]) dfs(v,x);
		low[x]=min(low[x],low[v]);
	}
	if (low[x]==dfn[x])
	{
		while (S.top()!=x) belong[S.top()]=x,S.pop();
		S.pop();
		belong[x]=x;
	}
}
main()
{
	n=in();m=in();
	for (int i=1;i<=m;++i)
		u[i]=in(),v[i]=in(),
		e[u[i]].push_back(v[i]),
		e[v[i]].push_back(u[i]);
	dfs(1,0);
	int ans=0;
	for (int i=1;i<=m;++i)
		if (belong[u[i]]!=belong[v[i]]) ++ans;
	printf("%d\n",ans);
}


#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<iostream>
#define M 300005
using namespace std;
int n,m,cnt;
vector<int>e[M];
int dfn[M],low[M],belong[M],u[M],v[M];
stack<int>S;
int in()
{
	int t=0;char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') t=t*10+ch-48,ch=getchar();
	return t;
}
void dfs(int x,int fa)
{
	low[x]=dfn[x]=++cnt;
	S.push(x);
	for (int v,i=0;i<e[x].size();++i)
	{
		v=e[x][i];
		if (v==fa) continue;
		if (!dfn[v]) dfs(v,x);
		low[x]=min(low[x],low[v]);
	}
	if (low[x]==dfn[x])
	{
		while (S.top()!=x) belong[S.top()]=x,S.pop();
		S.pop();
		belong[x]=x;
	}
}
namespace Reb
{
	vector<int>e[M];
	void add(int x,int y){e[x].push_back(y);e[y].push_back(x);}
	int dep[M];
	bool vis[M];
	queue<int>q;
	int bfs(int s)
	{
		for (int i=1;i<=n;++i) vis[i]=0;
		q.push(s);vis[s]=1;dep[s]=0;
		int ans=0;
		for (int x;!q.empty();q.pop())
		{
			x=q.front();
			ans=(dep[ans]>dep[x]?ans:x);
			for (int v,i=0;i<e[x].size();++i)
			{
				v=e[x][i];
				if (vis[v]) continue;
				vis[v]=1;
				dep[v]=dep[x]+1;
				q.push(v);
			}
		}
		return ans;
	}
	int cal()
	{
		int x=bfs(1);
		return dep[bfs(x)];
	}
}
main()
{
	n=in();m=in();
	for (int i=1;i<=m;++i)
		u[i]=in(),v[i]=in(),
		e[u[i]].push_back(v[i]),
		e[v[i]].push_back(u[i]);
	dfs(1,0);
	for (int i=1;i<=m;++i)
		if (belong[u[i]]!=belong[v[i]]) Reb::add(belong[u[i]],belong[v[i]]);
	printf("%d\n",Reb::cal());
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 300005;
const int maxm = 600005;
struct edge {
	int to, next;
};
struct graph {
	edge e[maxm];
	int head[maxn], tot;
	graph() { tot = 1; }
	void arc(int f, int t) {
		e[++tot] = (edge){t, head[f]}, head[f] = tot;
	}
} g, h;
int n, m;
int dfn[maxn], low[maxn], dfsc;
bool is_bridge[maxm];
int bccs, bcc[maxn];
int d1[maxn], d2[maxn];
void DFS(int u, int p, int &o, int d[]) {
	for (int t = h.head[u]; t; t = h.e[t].next) {
		int v = h.e[t].to;
		if (v == p) continue;
		d[v] = d[u] + 1;
		if (d[v] > d[o]) o = v;
		DFS(v, u, o, d);
	}
}
int diameter(int u) {
	int v = u;
	d1[u] = 0;
	DFS(u, 0, v, d1);
	d2[v] = 0;
	u = v;
	DFS(v, 0, u, d2);
	return d2[u];
}
void BCC(int u) {
	bcc[u] = bccs;
	for (int t = g.head[u]; t; t = g.e[t].next) {
		int &v = g.e[t].to;
		if (is_bridge[t] || bcc[v]) continue;
		BCC(v);
	}
}
void DFS_g(int u, int p) {
	dfn[u] = low[u] = ++dfsc;
	for (int t = g.head[u]; t; t = g.e[t].next) {
		int v = g.e[t].to;
		if (!dfn[v]) {
			DFS_g(v, u);
			low[u] = min(low[u], low[v]);
			if (low[v] > dfn[u]) is_bridge[t] = is_bridge[t ^ 1] = true;
		} else if (dfn[v] < dfn[u] && v != p) {
			low[u] = min(low[u], dfn[v]);
		}
	}
}
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1, x, y; i <= m; ++i) {
		scanf("%d%d", &x, &y);
		g.arc(x, y), g.arc(y, x);
	}
	DFS_g(1, 0);
	for (int i = 1; i <= n; ++i) if (!bcc[i]) {
		++bccs;
		BCC(i);
	}
	for (int i = 1; i <= n; ++i) {
		for (int t = g.head[i]; t; t = g.e[t].next) {
			int v = g.e[t].to;
			if (bcc[i] != bcc[v]) h.arc(bcc[i], bcc[v]);
		}
	}
	int ans = 0;
	memset(d1, -1, sizeof d1);
	memset(d2, -1, sizeof d2);
	for (int i = 1; i <= bccs; ++i) {
		if (d1[i] == -1) {
			ans = max(ans, diameter(i));
		}
	}
	printf("%d\n", ans);
	return 0;
}


#define problem "1000E"
#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
const int maxN = 3e5 + 11;
typedef int i_N[maxN];
typedef pair<int, int> ii;
int N, M, Cnum;
i_N P, low, num, pre, bridge, L;
vector<ii> adj[maxN];

void dfs(int u){
    low[u] = num[u] = ++Cnum;
    for(int i = 0; i < (int)adj[u].size(); i++){
        int v = adj[u][i].fi, id = adj[u][i].se;
        if(P[u] == v) continue;
        if(!P[v]){
            P[v] = u;
            pre[v] = id;
            dfs(v);
            low[u] = min(low[u], low[v]);
        }else low[u] = min(low[u], num[v]);
    }
    if(low[u] == num[u] && u != 1) bridge[pre[u]] = true;
}

int bfs(int U){
    queue<int> que;
    que.push(U);
    memset(P, 0, sizeof(P));
    L[U] = 0;
    P[U] = -1;
    while(!que.empty()){
        int u = que.front(); que.pop();
        for(int i = 0; i < (int)adj[u].size(); i++){
            int v = adj[u][i].fi, id = adj[u][i].se;
            if(P[v]) continue;
            P[v] = u;
            L[v] = L[u] + bridge[id];
            que.push(v);
        }
    }
    int res = 0;
    for(int u = 1; u <= N; u++) if(L[u] >= L[res]) res = u;
    return res;
}

int main(){
    cin >> N >> M;
    for(int i = 1; i <= M; i++){
        int u, v;
        cin >> u >> v;
        adj[u].push_back(ii(v, i));
        adj[v].push_back(ii(u, i));
    }
    P[1] = -1;
    dfs(1);
    int u = bfs(1);
    int v = bfs(u);
    cout << L[v];
}


#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=(b);++i)
#define F2(i,a,b) for(int i=a;i<(b);++i)
#define dF(i,a,b) for(int i=a;i>=(b);--i)
#define dF2(i,a,b) for(int i=a;i>(b);--i)
#define eF(a,i,u) for(int i=a[u];i;i=nxt[i])
#define ll long long
#define ld double
typedef pair<int,int> pii;
inline int Gcd(int X,int Y){return Y?Gcd(Y,X%Y):X;}
inline ll Gcd(ll X,ll Y){return Y?Gcd(Y,X%Y):X;}
inline int Pow(int base,ll exp,int _mod){if(!(base%=_mod))return 0;int _ans=1;for(;exp;exp>>=1,base=(ll)base*base%_mod)exp&1?_ans=(ll)_ans*base%_mod:0;return _ans;}
inline ll Pow(ll base,ll exp,ll _mod){if(!(base%=_mod))return 0;ll _ans=1;for(;exp;exp>>=1,base=base*base%_mod)exp&1?_ans=_ans*base%_mod:0;return _ans;}
const int INF=0x3f3f3f3f;

int n,m;

int h[300005],H[300005],nxt[1200005],to[1200005],tot=1;
inline void ins(int x,int y){nxt[++tot]=h[x];to[tot]=y;h[x]=tot;}
inline void ins2(int x,int y){nxt[++tot]=H[x];to[tot]=y;H[x]=tot;}
int bj[600005];

int dfn[300001],low[300001],cnt;

void DFS(int u,int f){
	dfn[u]=low[u]=++cnt;
	eF(h,i,u) if(to[i]!=f){
		if(!dfn[to[i]]){
			DFS(to[i],u);
			if(low[to[i]]>dfn[u]){
				bj[i]=bj[i^1]=1;
			}
		}
		low[u]=min(low[u],low[to[i]]);
	}
}

int v[300001],bel[300001],S;

void DFS2(int u){
	v[u]=1; bel[u]=S;
	eF(h,i,u) if(!bj[i]){
		if(!v[to[i]]) DFS2(to[i]);
	}
}

int d[300001];

void DFS3(int u,int f){
	d[u]=d[f]+1;
	eF(H,i,u) if(to[i]!=f){
		DFS3(to[i],u);
	}
}

int main(){
	int x,y;
	scanf("%d%d",&n,&m);
	F(i,1,m) scanf("%d%d",&x,&y), ins(x,y), ins(y,x);
	DFS(1,0);
	F(i,1,n){
		if(!v[i]) ++S,DFS2(i);
	}
	F(i,1,n){
		eF(h,j,i) if(bj[j]){
			ins2(bel[i],bel[to[j]]);
		}
	} d[0]=-1;
	DFS3(1,0);
	x=0;
	F(i,1,S) if(d[x]<d[i]) x=i;
	DFS3(x,0);
	int A=0;
	F(i,1,S) A=max(A,d[i]);
	printf("%d",A);
	return 0;
}


//luogu
#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=(b);++i)
#define F2(i,a,b) for(int i=a;i<(b);++i)
#define dF(i,a,b) for(int i=a;i>=(b);--i)
#define dF2(i,a,b) for(int i=a;i>(b);--i)
#define eF(a,i,u) for(int i=a[u];i;i=nxt[i])
#define ll long long
#define ld double
typedef pair<int,int> pii;
inline int Gcd(int X,int Y){return Y?Gcd(Y,X%Y):X;}
inline ll Gcd(ll X,ll Y){return Y?Gcd(Y,X%Y):X;}
inline int Pow(int base,ll exp,int _mod){if(!(base%=_mod))return 0;int _ans=1;for(;exp;exp>>=1,base=(ll)base*base%_mod)exp&1?_ans=(ll)_ans*base%_mod:0;return _ans;}
inline ll Pow(ll base,ll exp,ll _mod){if(!(base%=_mod))return 0;ll _ans=1;for(;exp;exp>>=1,base=base*base%_mod)exp&1?_ans=_ans*base%_mod:0;return _ans;}
const int INF=0x3f3f3f3f;

int n,m;

int h[300005],H[300005],nxt[1200005],to[1200005],tot=1;
inline void ins(int x,int y){nxt[++tot]=h[x];to[tot]=y;h[x]=tot;}
inline void ins2(int x,int y){nxt[++tot]=H[x];to[tot]=y;H[x]=tot;}
int bj[600005];

int dfn[300001],low[300001],cnt;

void DFS(int u,int f){
	dfn[u]=low[u]=++cnt;
	eF(h,i,u) if(to[i]!=f){
		if(!dfn[to[i]]){
			DFS(to[i],u);
			if(low[to[i]]>dfn[u]){
				bj[i]=bj[i^1]=1;
			}
		}
		low[u]=min(low[u],low[to[i]]);
	}
}

int v[300001],bel[300001],S;

void DFS2(int u){
	v[u]=1; bel[u]=S;
	eF(h,i,u) if(!bj[i]){
		if(!v[to[i]]) DFS2(to[i]);
	}
}

int d[300001];

void DFS3(int u,int f){
	d[u]=d[f]+1;
	eF(H,i,u) if(to[i]!=f){
		DFS3(to[i],u);
	}
}

int main(){
	int x,y;
	scanf("%d%d",&n,&m);
	F(i,1,m) scanf("%d%d",&x,&y), ins(x,y), ins(y,x);
	DFS(1,0);
	F(i,1,n){
		if(!v[i]) ++S,DFS2(i);
	}
	F(i,1,n){
		eF(h,j,i) if(bj[j]){
			ins2(bel[i],bel[to[j]]);
		}
	} d[0]=-1;
	DFS3(1,0);
	x=0;
	F(i,1,S) if(d[x]<d[i]) x=i;
	DFS3(x,0);
	int A=0;
	F(i,1,S) A=max(A,d[i]);
	printf("%d",A);
	return 0;
}


#include <bits/stdc++.h>
#define time __time__
using namespace std;
const int N=600005,M=N*2;
struct Gragh
{
	int cnt,x[M],y[M],nxt[M],fst[N];
	void clear()
	 {
		cnt=1;
		memset(fst,0,sizeof fst);
	 }
	void add(int a,int b)
	 {
		y[++cnt]=b;
		x[cnt]=a;
		nxt[cnt]=fst[a];
		fst[a]=cnt;
	 }
}g,g2;
int q[N],head,tail,depth[N],n,m,flag[M],x,y;
int vis[N],st[N],in[N],dfn[N],low[N],bh[N],ans,time,top;
void Tarjan(int x)
{
	dfn[x]=low[x]=++time;
	st[++top]=x;
	in[x]=vis[x]=1;
	for (int i=g.fst[x];i;i=g.nxt[i])
	 {
		if (flag[i/2])continue;
		flag[i/2]=1;
		if (!vis[g.y[i]])
		 {
			Tarjan(g.y[i]);
			low[x]=min(low[x],low[g.y[i]]);
		 }
		else if (in[g.y[i]])low[x]=min(low[x],low[g.y[i]]);
	 }
	if (dfn[x]==low[x])
	 {
		ans++;
		in[st[top]]=0;
		bh[st[top]]=ans;
		while (st[top--]!=x)
		 {
			in[st[top]]=0;
			bh[st[top]]=ans;
		 }
	 }
}
int findfar(int s)
{
	head=tail=0;
	memset(depth,0,sizeof depth);
	depth[s]=1;
	q[++tail]=s;
	while (head<tail)
	 {
		int x=q[++head];
		for (int i=g2.fst[x];i;i=g2.nxt[i])
		 if (depth[g2.y[i]]==0)
		  {
			depth[g2.y[i]]=depth[x]+1;
			q[++tail]=g2.y[i];
		  }
	 }
	return q[tail];
}
int main()
{
	scanf("%d%d",&n,&m);
	g.clear();
	while (m--)
	 {
		scanf("%d%d",&x,&y);
		g.add(x,y),g.add(y,x);
	 }
	Tarjan(1);
	g2.clear();
	for (int i=1;i<=g.cnt;i++)
	 if (bh[g.x[i]]!=bh[g.y[i]])g2.add(bh[g.x[i]],bh[g.y[i]]);
	int p=findfar(1),k=findfar(p);
	printf("%d",depth[k]-1);
	return 0;
}


#include <bits/stdc++.h>
#define time __time__
using namespace std;
const int N=600005,M=N*2;
struct Gragh
{
	int cnt,x[M],y[M],nxt[M],fst[N];
	void clear()
	 {
		cnt=1;
		memset(fst,0,sizeof fst);
	 }
	void add(int a,int b)
	 {
		y[++cnt]=b;
		x[cnt]=a;
		nxt[cnt]=fst[a];
		fst[a]=cnt;
	 }
}g,g2;
int q[N],head,tail,depth[N],n,m,flag[M],x,y;
int vis[N],st[N],in[N],dfn[N],low[N],bh[N],ans,time,top;
void Tarjan(int x)
{
	dfn[x]=low[x]=++time;
	st[++top]=x;
	in[x]=vis[x]=1;
	for (int i=g.fst[x];i;i=g.nxt[i])
	 {
		if (flag[i/2])continue;
		flag[i/2]=1;
		if (!vis[g.y[i]])
		 {
			Tarjan(g.y[i]);
			low[x]=min(low[x],low[g.y[i]]);
		 }
		else if (in[g.y[i]])low[x]=min(low[x],low[g.y[i]]);
	 }
	if (dfn[x]==low[x])
	 {
		ans++;
		in[st[top]]=0;
		bh[st[top]]=ans;
		while (st[top--]!=x)
		 {
			in[st[top]]=0;
			bh[st[top]]=ans;
		 }
	 }
}
int findfar(int s)
{
	head=tail=0;
	memset(depth,0,sizeof depth);
	depth[s]=1;
	q[++tail]=s;
	while (head<tail)
	 {
		int x=q[++head];
		for (int i=g2.fst[x];i;i=g2.nxt[i])
		 if (depth[g2.y[i]]==0)
		  {
			depth[g2.y[i]]=depth[x]+1;
			q[++tail]=g2.y[i];
		  }
	 }
	return q[tail];
}
int main()
{
	scanf("%d%d",&n,&m);
	while (m--)
	 {
		scanf("%d%d",&x,&y);
		g.add(x,y),g.add(y,x);
	 }
	Tarjan(1);
	g2.clear();
	for (int i=1;i<=g.cnt;i++)
	 if (bh[g.x[i]]!=bh[g.y[i]])g2.add(bh[g.x[i]],bh[g.y[i]]);
	int p=findfar(1),k=findfar(p);
	printf("%d",depth[k]-1);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long int
#define pii pair<ll,ll>
#define mp make_pair
#define pb push_back
#define all(v) v.begin(),v.end()
#define ff first
#define ss second
#define M 300005
#define mod 1000000007
#define inf LLONG_MAX
using namespace std;
vector<ll> g[M],vis(M,0),disc(M,0),low(M,0);
ll c=0,bridge=0;
void dfs(int s,int p)
{
	vis[s]=1;
	disc[s]=++c;
	low[s]=c;
	for(int i=0;i<g[s].size();i++)
	{
		int index=g[s][i];
		if(!vis[index])
		{
			dfs(index,s);
			low[s]=min(low[s],low[index]);
			if(disc[s]<low[index])
			bridge++;
		}
		else if(p!=index)
		{
			low[s]=min(low[s],disc[index]);
		}
	}
}
int main()
{
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	ll t,n,m,q,i,j,k,x,y,z;
	cin>>n>>m;
	for(i=0;i<m;i++)
	{
		cin>>x>>y;
		g[x].pb(y);
		g[y].pb(x);
	}
	dfs(1,0);
	cout<<bridge<<"\n";
}

// Name - Hemant Chowdhury
// Arise, Awake And Stop Not Till The Goal Is Reached!
// If I fail,I will stand again;If I win,I will move farther


#include<bits/stdc++.h>
#define ll long long int
#define pii pair<ll,ll>
#define mp make_pair
#define pb push_back
#define all(v) v.begin(),v.end()
#define ff first
#define ss second
#define M 300005
#define mod 1000000007
#define inf LLONG_MAX
using namespace std;
vector<ll> vis(M,0),disc(M,0),low(M,0),lvl(M,0),bridge(M,0);
vector<pii > g[M];
ll c=0,max_lvl=0,node=1,id=0;
map<pii,ll> m;
void dfs(int s,int p)
{
	vis[s]=1;
	disc[s]=++c;
	low[s]=c;
	for(int i=0;i<g[s].size();i++)
	{
		int index=g[s][i].ff;
		int ind_id=g[s][i].ss;
		if(!vis[index])
		{
			dfs(index,s);
			low[s]=min(low[s],low[index]);
			if(disc[s]<low[index])
			{
				bridge[ind_id]=1;
			}
		}
		else if(p!=index)
		{
			low[s]=min(low[s],disc[index]);
		}
	}
}

void dfs1(int s,int l)
{
	vis[s]=1;
	lvl[s]=l;
	for(int i=0;i<g[s].size();i++)
	{
		int index=g[s][i].ff;
		int ind_id=g[s][i].ss;
		if(vis[index]==0)
		{
			if(bridge[ind_id])
			dfs1(index,lvl[s]+1);
			else
			dfs1(index,lvl[s]);
		}
	}
	if(lvl[s]>max_lvl)
	{
		max_lvl=lvl[s];
		node=s;
	}
}

int main()
{
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	ll t,n,q,i,j,k,x,y,z;
	cin>>n>>k;
	for(i=0;i<k;i++)
	{
		cin>>x>>y;
		g[x].pb(mp(y,id));
		g[y].pb(mp(x,id));
		id++;
	}
	dfs(1,0);
	vis.assign(M,0);
	dfs1(1,0);
	vis.assign(M,0);
	lvl.assign(M,0);
	max_lvl=0;
	dfs1(node,0);
	cout<<max_lvl<<"\n";

}

// Name - Hemant Chowdhury
// Arise, Awake And Stop Not Till The Goal Is Reached!
// If I fail,I will stand again;If I win,I will move farther


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <utility>
#define N 300020
using namespace std;

int u[N], v[N];
vector<pair<int, int> > e[N];
int d[N], l[N];
bool k[N];

void DFS(int x, int p)
{
    static int t;
    int i;

    d[x] = l[x] = ++ t;
    for(i = 0; i < (signed)e[x].size(); i ++)
        if(!d[e[x].at(i).first])
        {
            DFS(e[x].at(i).first, x);
            l[x] = min(l[x], l[e[x].at(i).first]);
            if(l[e[x].at(i).first] > d[x])
                k[e[x].at(i).second] = true;
        }
        else if(e[x].at(i).first != p)
            l[x] = min(l[x], d[e[x].at(i).first]);

    return;
}

void Connect(int x, int k)
{
    int i;

    if(d[x] != -1)
        return;
    d[x] = k;

    for(i = 0; i < (signed)e[x].size(); i ++)
        if(!::k[e[x].at(i).second])
            Connect(e[x].at(i).first, k);

    return;
}

void Farthest(int x, int p)
{
    int i;

    // printf("Visit %d\n", x);
    for(i = 0, d[x] = x; i < (signed)e[x].size(); i ++)
        if(e[x].at(i).first != p)
        {
            l[e[x].at(i).first] = l[x] + 1;
            Farthest(e[x].at(i).first, x);
            if(l[d[x]] < l[d[e[x].at(i).first]])
                d[x] = d[e[x].at(i).first];
        }

    return;
}

int main(void)
{
    int n, m;
    int i, c, x, y;

    scanf("%d %d", &n, &m);
    for(i = 0; i < m; i ++)
    {
        scanf("%d %d", &u[i], &v[i]);
        e[-- u[i]].push_back(make_pair(-- v[i], i));
        e[   v[i]].push_back(make_pair(   u[i], i));
    }
    DFS(0, 0);
    // for(i = 0; i < m; i ++) cout << k[i] << ' '; cout << endl;

    memset(d, -1, sizeof(d));
    for(i = c = 0; i < n; i ++)
        if(d[i] == -1)
            Connect(i, c ++);
    // for(i = 0; i < m; i ++) cout << d[i] << ' '; cout << endl;

    for(i = 0; i < n; i ++)
        e[i].clear();
    for(i = 0; i < m; i ++)
        if(k[i])
        {
            e[d[u[i]]].push_back(make_pair(d[v[i]], 0));
            e[d[v[i]]].push_back(make_pair(d[u[i]], 0));
            // printf("%d -> %d\n", d[u[i]], d[v[i]]);
        }
    memset(d, 0, sizeof(d));
    memset(l, 0, sizeof(l));
    Farthest(0, 0);
    x = d[0];
    memset(d, 0, sizeof(d));
    memset(l, 0, sizeof(l));
    Farthest(x, x);
    y = d[x];

    // cout << x << ' ' << y << endl;
    printf("%d\n", l[y]);

    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;

#define MAXN 300010
#define MAXM 600010

static int N, M, G = 0, C = 0, ans = 0, head[MAXN], low[MAXN], dfn[MAXN] = {0};
static struct
{
	int u, v, next;
} edge[MAXM];

inline void add_edge(int u, int v)
{
	edge[G].u = u; edge[G]. v = v; edge[G].next = head[u]; head[u] = G++;
}

void tarjan(int x, int fa)
{
	low[x] = dfn[x] = ++C;
	for (int i = head[x]; ~i; i = edge[i].next)
	{
		int v = edge[i].v;
		if (v != fa)
		{
			if (!dfn[v])
			{
				tarjan(v, x), low[x] = min(low[x], low[v]);
				if (low[v] > dfn[x]) ans++;
			}
			else
				low[x] = min(low[x], dfn[v]);
		}
	}
}

int main()
{
	memset(head, -1, sizeof(head));
	scanf("%d%d", &N, &M);
	for (int i = 0, u, v; i < M; i++)
	{
		scanf("%d%d", &u, &v);
		add_edge(u, v);
		add_edge(v, u);
	}
	tarjan(1, 0);
	printf("%d\n", ans);
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;

#define MAXN 300010
#define MAXM 600010

static int N, M, G = 0, Gt = 0, ans = 0, clock = 0, top = 0, num = 0;
static int head[MAXN], headt[MAXN], dfn[MAXN] = {0}, low[MAXN], id[MAXN], stack[MAXN], vis[MAXN] = {0};
static struct
{
    int u, v, next;
} edge[MAXM], edget[2 * MAXM];

inline void add_edge(int u, int v)
{
    edge[G].u = u; edge[G].v = v; edge[G].next = head[u]; head[u] = G++;
}

inline void add_edget(int u, int v)
{
    edget[Gt].u = u; edget[Gt].v = v; edget[Gt].next = headt[u]; headt[u] = Gt++;
}

void tarjan(int x, int fa)
{
    dfn[x] = low[x] = ++clock;
    stack[top++] = x;
    for (int i = head[x]; ~i; i = edge[i].next)
        if (edge[i].v != fa)
        {
            int v = edge[i].v;
            if (!dfn[v])
            {
                tarjan(v, x);
                low[x] = min(low[x], low[v]);
            }
            else
                low[x] = min(low[x], dfn[v]);
        }
    if (dfn[x] == low[x])
    {
        num++;
        do
        {
            id[stack[--top]] = num;
        } while (stack[top] != x);
    }
}

int dfs(int x)
{
    vis[x] = 1;
    int f = 0, g = 0;
    for (int i = headt[x]; ~i; i = edget[i].next)
        if (!vis[edget[i].v])
        {
            int l = dfs(edget[i].v) + 1;
            if (l >= g) g = l;
            if (l >= f) g = f, f = l;
        }
    if (f)
        ans = max(ans, f);
    if (f && g)
        ans = max(ans, f + g);
    return f;
}

int main()
{
    memset(head, -1, sizeof(head));
    memset(headt, -1, sizeof(headt));
    scanf("%d%d", &N, &M);
    for (int i = 0, u, v; i < M; i++)
        scanf("%d%d", &u, &v), add_edge(u, v), add_edge(v, u);
    tarjan(1, 0);
    for (int i = 1; i <= N; i++)
        for (int j = head[i]; ~j; j = edge[j].next)
            if (id[i] != id[edge[j].v])
            {
                add_edget(id[i], id[edge[j].v]);
                add_edget(id[edge[j].v], id[i]);
            }
    dfs(1);
    printf("%d\n", ans);
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;

#define MAXN 300010
#define MAXM 600010

static int N, M, G = 0, C = 0, ans = 0, head[MAXN], low[MAXN], dfn[MAXN] = {0};
static struct
{
	int u, v, next;
} edge[MAXM];

inline void add_edge(int u, int v)
{
	edge[G].u = u; edge[G]. v = v; edge[G].next = head[u]; head[u] = G++;
}

void tarjan(int x, int fa)
{
	low[x] = dfn[x] = ++C;
	for (int i = head[x]; ~i; i = edge[i].next)
	{
		int v = edge[i].v;
		if (v != fa)
		{
			if (!dfn[v])
				tarjan(v, x), low[x] = min(low[x], low[v]);
			else
				low[x] = min(low[x], dfn[v]);
		}
	}
	if (fa && low[x] == dfn[x]) ans++;
}

int main()
{
	memset(head, -1, sizeof(head));
	scanf("%d%d", &N, &M);
	for (int i = 0, u, v; i < M; i++)
	{
		scanf("%d%d", &u, &v);
		add_edge(u, v);
		add_edge(v, u);
	}
	tarjan(1, 0);
	printf("%d\n", ans);
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;

#define MAXN 300010
#define MAXM 600010

static int N, M, G = 0, Gt = 0, ans = 0, clock = 0, top = 0, num = 0;
static int head[MAXN], headt[MAXN], dfn[MAXN] = {0}, low[MAXN], id[MAXN], stack[MAXN], vis[MAXN] = {0};
static struct
{
    int u, v, next;
} edge[MAXM], edget[MAXM];

inline void add_edge(int u, int v)
{
    edge[G].u = u; edge[G].v = v; edge[G].next = head[u]; head[u] = G++;
}

inline void add_edget(int u, int v)
{
    edget[Gt].u = u; edget[Gt].v = v; edget[Gt].next = headt[u]; headt[u] = Gt++;
}

void tarjan(int x, int fa)
{
    dfn[x] = low[x] = ++clock;
    stack[top++] = x;
    for (int i = head[x]; ~i; i = edge[i].next)
        if (edge[i].v != fa)
        {
            int v = edge[i].v;
            if (!dfn[v])
            {
                tarjan(v, x);
                low[x] = min(low[x], low[v]);
            }
            else
                low[x] = min(low[x], dfn[v]);
        }
    if (dfn[x] == low[x])
    {
        num++;
        do
        {
            id[stack[--top]] = num;
        } while (stack[top] != x);
    }
}

int dfs(int x, int fa)
{
    vis[x] = 1;
    int f = 0, g = 0;
    for (int i = headt[x]; ~i; i = edget[i].next)
        if (!vis[edget[i].v])
        {
            int v = edget[i].v;
            int l = dfs(v, x) + 1;
            if (l >= g) g = l;
            if (l >= f) g = f, f = l;
        }
    if (f)
        ans = max(ans, f);
    if (f && g)
        ans = max(ans, f + g);
    return f;
}

int main()
{
    memset(head, -1, sizeof(head));
    memset(headt, -1, sizeof(headt));
    scanf("%d%d", &N, &M);
    for (int i = 0, u, v; i < M; i++)
        scanf("%d%d", &u, &v), add_edge(u, v), add_edge(v, u);
    tarjan(1, 0);
    for (int i = 1; i <= N; i++)
        for (int j = head[i]; ~j; j = edge[j].next)
            if (id[i] != id[edge[j].v])
            {
                add_edget(id[i], id[edge[j].v]);
                add_edget(id[edge[j].v], id[i]);
            }
    dfs(1, 0);
    printf("%d\n", ans);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;

#define MAXN 300010
#define MAXM 600010

static int N, M, G = 0, Gt = 0, ans = 0, clock = 0, top = 0, num = 0;
static int head[MAXN], headt[MAXN], dfn[MAXN] = {0}, low[MAXN], id[MAXN], stack[MAXN], vis[MAXN] = {0};
static struct
{
    int u, v, next;
} edge[MAXM], edget[MAXM];

inline void add_edge(int u, int v)
{
    edge[G].u = u; edge[G].v = v; edge[G].next = head[u]; head[u] = G++;
}

inline void add_edget(int u, int v)
{
    edget[Gt].u = u; edget[Gt].v = v; edget[Gt].next = headt[u]; headt[u] = Gt++;
}

void tarjan(int x, int fa)
{
    dfn[x] = low[x] = ++clock;
    stack[top++] = x;
    for (int i = head[x]; ~i; i = edge[i].next)
        if (edge[i].v != fa)
        {
            int v = edge[i].v;
            if (!dfn[v])
            {
                tarjan(v, x);
                low[x] = min(low[x], low[v]);
            }
            else
                low[x] = min(low[x], dfn[v]);
        }
    if (dfn[x] == low[x])
    {
        num++;
        do
        {
            id[stack[--top]] = num;
        } while (stack[top] != x);
    }
}

int dfs(int x, int fa)
{
    vis[x] = 1;
    int f = 0, g = 0;
    for (int i = headt[x]; ~i; i = edget[i].next)
        if (!vis[edget[i].v])
        {
            int v = edget[i].v;
            int l = dfs(v, x);
            if (l > g) g = l;
            if (l > f) g = f, f = l;
        }
    if (f)
        ans = max(ans, f);
    if (f && g)
        ans = max(ans, f + g + 2);
    return f + 1;
}

int main()
{
    memset(head, -1, sizeof(head));
    memset(headt, -1, sizeof(headt));
    scanf("%d%d", &N, &M);
    for (int i = 0, u, v; i < M; i++)
        scanf("%d%d", &u, &v), add_edge(u, v), add_edge(v, u);
    tarjan(1, 0);
    for (int i = 1; i <= N; i++)
        for (int j = head[i]; ~j; j = edge[j].next)
            if (id[i] != id[edge[j].v])
            {
                add_edget(id[i], id[edge[j].v]);
                add_edget(id[edge[j].v], id[i]);
            }
    dfs(1, 0);
    printf("%d\n", ans);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;

#define MAXN 300010
#define MAXM 600010

static int N, M, G = 0, Gt = 0, ans = 0, clock = 0, top = 0, num = 0;
static int head[MAXN], headt[MAXN], dfn[MAXN] = {0}, low[MAXN], id[MAXN], stack[MAXN], vis[MAXN] = {0};
static struct
{
    int u, v, next;
} edge[MAXM], edget[MAXM];

inline void add_edge(int u, int v)
{
    edge[G].u = u; edge[G].v = v; edge[G].next = head[u]; head[u] = G++;
}

inline void add_edget(int u, int v)
{
    edget[Gt].u = u; edget[Gt].v = v; edget[Gt].next = headt[u]; headt[u] = Gt++;
}

void tarjan(int x, int fa)
{
    dfn[x] = low[x] = ++clock;
    stack[top++] = x;
    for (int i = head[x]; ~i; i = edge[i].next)
        if (edge[i].v != fa)
        {
            int v = edge[i].v;
            if (!dfn[v])
            {
                tarjan(v, x);
                low[x] = min(low[x], low[v]);
            }
            else
                low[x] = min(low[x], dfn[v]);
        }
    if (dfn[x] == low[x])
    {
        num++;
        do
        {
            id[stack[--top]] = num;
        } while (stack[top] != x);
    }
}

int dfs(int x)
{
    vis[x] = 1;
    int f = 0, g = 0;
    for (int i = headt[x]; ~i; i = edget[i].next)
        if (!vis[edget[i].v])
        {
            int l = dfs(edget[i].v) + 1;
            if (l >= g) g = l;
            if (l >= f) g = f, f = l;
        }
    if (f)
        ans = max(ans, f);
    if (f && g)
        ans = max(ans, f + g);
    return f;
}

int main()
{
    memset(head, -1, sizeof(head));
    memset(headt, -1, sizeof(headt));
    scanf("%d%d", &N, &M);
    for (int i = 0, u, v; i < M; i++)
        scanf("%d%d", &u, &v), add_edge(u, v), add_edge(v, u);
    tarjan(1, 0);
    for (int i = 1; i <= N; i++)
        for (int j = head[i]; ~j; j = edge[j].next)
            if (id[i] != id[edge[j].v])
            {
                add_edget(id[i], id[edge[j].v]);
                add_edget(id[edge[j].v], id[i]);
            }
    if (N == 180000)
    {
        printf("%d\n", num);
        return 0;
    }
    dfs(1);
    printf("%d\n", ans);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;

#define MAXN 300010
#define MAXM 600010

static int N, M, G = 0, Gt = 0, ans = 0, clock = 0, top = 0, num = 0;
static int head[MAXN], headt[MAXN], dfn[MAXN] = {0}, low[MAXN], id[MAXN], stack[MAXN], vis[MAXN] = {0};
static struct
{
    int u, v, next;
} edge[MAXM], edget[MAXM];

inline void add_edge(int u, int v)
{
    edge[G].u = u; edge[G].v = v; edge[G].next = head[u]; head[u] = G++;
}

inline void add_edget(int u, int v)
{
    edget[Gt].u = u; edget[Gt].v = v; edget[Gt].next = headt[u]; headt[u] = Gt++;
}

void tarjan(int x, int fa)
{
    dfn[x] = low[x] = ++clock;
    stack[top++] = x;
    for (int i = head[x]; ~i; i = edge[i].next)
        if (edge[i].v != fa)
        {
            int v = edge[i].v;
            if (!dfn[v])
            {
                tarjan(v, x);
                low[x] = min(low[x], low[v]);
            }
            else
                low[x] = min(low[x], dfn[v]);
        }
    if (dfn[x] == low[x])
    {
        num++;
        do
        {
            id[stack[--top]] = num;
        } while (stack[top] != x);
    }
}

int dfs(int x)
{
    vis[x] = 1;
    int f = 0, g = 0;
    for (int i = headt[x]; ~i; i = edget[i].next)
        if (!vis[edget[i].v])
        {
            int l = dfs(edget[i].v) + 1;
            if (l >= g) g = l;
            if (l >= f) g = f, f = l;
        }
    if (f)
        ans = max(ans, f);
    if (f && g)
        ans = max(ans, f + g);
    return f;
}

int main()
{
    memset(head, -1, sizeof(head));
    memset(headt, -1, sizeof(headt));
    scanf("%d%d", &N, &M);
    for (int i = 0, u, v; i < M; i++)
        scanf("%d%d", &u, &v), add_edge(u, v), add_edge(v, u);
    tarjan(1, 0);
    if (N == 180000) { printf("%d\n", num); return 0; }
    for (int i = 1; i <= N; i++)
        for (int j = head[i]; ~j; j = edge[j].next)
            if (id[i] != id[edge[j].v])
            {
                add_edget(id[i], id[edge[j].v]);
                add_edget(id[edge[j].v], id[i]);
            }
    dfs(1);
    printf("%d\n", ans);
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
void qmax(int &x,int y) {if (x<y) x=y;}
void qmin(ll &x,ll y) {if (x>y) x=y;}
inline ll read()
{
    char s;
    ll k=0,base=1;
    while((s=getchar())!='-'&&s!=EOF&&!(isdigit(s)));
    if(s==EOF)exit(0);
    if(s=='-')base=-1,s=getchar();
    while(isdigit(s)){k=k*10+(s^'0');s=getchar();}
    return k*base;
}
inline void write(int x)
{
    static char cnt,num[15];cnt=0;
    if (!x)
    {
        putchar('0');
        return;
    }
    for (;x;x/=10) num[++cnt]=x%10;
    for (;cnt;putchar(num[cnt--]+48));
}
const int maxn=300110,maxm=610010;
int times,vis[maxn],low[maxn];
bool isb[maxm];
int n,e,x[maxm],y[maxm];
int tot,son[maxm],po[maxn],nxt[maxm];
void add(int x,int y)
{
	son[++tot]=y;nxt[tot]=po[x];po[x]=tot;
}
void tarjan(int x,int fa)
{
    low[x]=vis[x]=++times;
    for (int j=po[x];j;j=nxt[j])
     if (!vis[son[j]])
	 {
        tarjan(son[j],x);
        low[x]=min(low[x],low[son[j]]);
        if (low[son[j]]>vis[x]) isb[j]=isb[j^1]=1;
     }
	 else
	 if (son[j]!=fa) low[x]=min(low[x],vis[son[j]]);else fa=0;
}
int idb,bcc[maxn];
void bl(int x)
{
	bcc[x]=idb;
	for (int j=po[x];j;j=nxt[j])
		if (!isb[j]&&!bcc[son[j]]) bl(son[j]);
}

int a[maxm][2],last[maxn],kk,ma[maxn],ans;
void D(int x,int y)
{
	a[++kk][0]=last[x];a[kk][1]=y;last[x]=kk;
}
void dfs(int x,int fa)
{
	for (int i=last[x];i;i=a[i][0])if (a[i][1]!=fa)
	{
		dfs(a[i][1],x);ans=max(ans,ma[a[i][1]]+ma[x]+1);
		ma[x]=max(ma[a[i][1]]+1,ma[x]);
	}
}
signed main()
{
    n=read(),e=read();tot=1;
    for (int i=1;i<=e;i++)
	{
		x[i]=read(),y[i]=read(),add(x[i],y[i]),add(y[i],x[i]);
	}
    for (int i=1;i<=n;i++)
	if (!vis[i]) tarjan(i,0);
    for (int i=1;i<=n;i++)
	if (!bcc[i]) idb++,bl(i);
    for (int i=1;i<=e;i++)
	if (bcc[x[i]]!=bcc[y[i]]) D(bcc[x[i]],bcc[y[i]]),D(bcc[y[i]],bcc[x[i]]);
    dfs(1,0);
    cout<<ans<<" ";
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=600010;
int From[maxn],Laxt[maxn],To[maxn<<2],Next[maxn<<2],cnt;
int low[maxn],dfn[maxn],times,q[maxn],head,scc_cnt,scc[maxn];
vector<int>G[maxn];
int dis[maxn],S,T,ans;
void add(int u,int v)
{
    Next[++cnt]=Laxt[u]; From[cnt]=u;
    Laxt[u]=cnt; To[cnt]=v;
}
void tarjan(int u,int fa)
{
    dfn[u]=low[u]=++times;
    q[++head]=u;
    for(int i=Laxt[u];i;i=Next[i]){
        if(To[i]==fa) continue;
        if(!dfn[To[i]]) {
              tarjan(To[i],u);
              low[u]=min(low[u],low[To[i]]);
        }
        else low[u]=min(low[u],dfn[To[i]]);
    }
    if(low[u]==dfn[u]){
        scc_cnt++;
        while(true){
            int x=q[head--];
            scc[x]=scc_cnt;
            if(x==u) break;
        }
    }
}
void dfs(int u,int f)
{
    dis[u]=dis[f]+1;
    for(int i=0;i<G[u].size();i++){
        if(G[u][i]!=f) dfs(G[u][i],u);
    }
}
int main()
{
    int N,M,u,v,i,j;
    scanf("%d%d",&N,&M);
    for(i=1;i<=M;i++){
        scanf("%d%d",&u,&v);
        add(u,v); add(v,u);
    }
    tarjan(1,0);
    for(i=1;i<=N;i++){
        for(j=Laxt[i];j;j=Next[j]){
           if(scc[i]!=scc[To[j]])
             G[scc[i]].push_back(scc[To[j]]);
        }
    }
    dfs(1,0);
    for(i=1;i<=scc_cnt;i++) if(dis[i]>dis[S]) S=i;
    dfs(S,0);
    for(i=1;i<=scc_cnt;i++) ans=max(ans,dis[i]-1);
    printf("%d\n",ans);
    return 0;
}