#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<memory.h>
#define MAX 5001
using namespace std;
int n, m, ord[MAX+1], low[MAX+1], od, sec[MAX+1], ss[MAX+1], DT[MAX][MAX], cnt;
bool visited[MAX+1];
vector<int> G[MAX+1];
set< pair<int, int> > S, CT;
void dfs(int v)
{
    visited[v] = true, ord[v] = ++od, low[v] = od;
    for(int i = 0 ; i < G[v].size() ; i++)
    {
        if( !visited[G[v][i]] )
            S.insert(make_pair(v,G[v][i])), dfs(G[v][i]), low[v] = min(low[v], low[G[v][i]]);
        else if( S.find(make_pair(G[v][i], v)) == S.end() )
            low[v] = min(low[v], ord[G[v][i]]);  // find back edge
        if( ord[v] < low[G[v][i]] )
            CT.insert(make_pair(v,G[v][i]));
    }
}
int area(int v)
{
    int s = 1;
    visited[v] = true;
    for(int i = 0 ; i < G[v].size(); i++ )
        if( !visited[G[v][i]] && CT.find(make_pair(v, G[v][i])) == CT.end() && CT.find(make_pair(G[v][i], v)) == CT.end() )
            s += area(G[v][i]);
    return s;
}
int solve(int a, int b)
{
    int ans = 987654321;
    if( a >= b ) return 0;
    if( DT[a][b] == 0 )
    {
        for(int k = a ; k < b ; k++ )
            ans = min(ans, ( solve(a,k)+solve(k+1,b) + (a?(ss[b]-ss[a-1]):ss[b]) ) );
        DT[a][b] = ans;
    }
    return DT[a][b];
}
int main()
{
    freopen(".20.in","r",stdin);
    freopen(".20.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i = 0 ; i < m ; i++ )
    {
        int a, b;
        scanf("%d%d",&a,&b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    dfs(1);
    memset(visited, 0, sizeof(visited));
    for(int i = 1 ; i <= n ; i++ )
        if( !visited[i] )
            sec[cnt++] = area(i);
    for(int i = 0 ; i < cnt ; i++ )
        if( i == 0 ) ss[i] = sec[i];
        else ss[i] = ss[i-1] + sec[i];
    printf("%d", solve(0, cnt-1));
}
