#include <bits/stdc++.h>
using namespace std;
int n, m;
const int infinito = 1000000000;
const int limite = 2001;
vector<int> g[limite];
int visto[limite];
int eliminado[limite];
int internos[limite];
int memcosteraiz[limite];
int calculadocosteraiz[limite];
int level[limite];
int padre[limite];
int puente[limite][limite];
int computapadre(int u) {
  if (padre[u] == 0) return u;
  padre[u] = computapadre(padre[u]);
  return padre[u];
}
void fusion(int u, int v) {
  u = computapadre(u);
  v = computapadre(v);
  if (u == v) return;
  padre[v] = u;
}
int costeraiz(int u) {
  int &mem = memcosteraiz[u];
  if (calculadocosteraiz[u]) return mem;
  calculadocosteraiz[u] = 1;
  vector<int> &ar = g[u];
  if (int(ar.size()) == 0) {
    mem = 0;
  } else {
    mem = infinito;
    for (int i = 0; i < int(ar.size()); i++)
      mem = min(mem, costeraiz(ar[i]) + internos[u] - 1 - internos[ar[i]]);
  }
  return mem;
}
int memcostepasaraiz[3000];
int calculadocostepasaraiz[3000];
int costepasaraiz(int u) {
  int &mem = memcostepasaraiz[u];
  if (calculadocostepasaraiz[u]) return mem;
  calculadocostepasaraiz[u] = 1;
  vector<int> &ar = g[u];
  mem = costeraiz(u);
  for (int i = 0; i < int(ar.size()); i++)
    for (int j = i + 1; j < int(ar.size()); j++)
      mem = min(mem, costeraiz(ar[i]) + costeraiz(ar[j]) + internos[u] - 1 -
                         internos[ar[i]] - internos[ar[j]]);
  return mem;
}
int computacoste(int u) {
  vector<int> &ar = g[u];
  int coste = costepasaraiz(u);
  for (int i = 0; i < int(ar.size()); i++) {
    int v = ar[i];
    int cv = computacoste(v);
    int crv = costepasaraiz(v);
    coste = min(coste, min(crv, cv + (int(g[v].size()) == 1)) + internos[u] -
                           1 + (int(ar.size()) > 1) - internos[v]);
  }
  return coste;
}
void eliminapadre(int u, int p) {
  visto[u] = 1;
  vector<int> &ar = g[u];
  vector<int> nextar;
  for (int i = 0; i < int(ar.size()); i++) {
    int v = ar[i];
    if (v != p) {
      eliminapadre(v, u);
      nextar.push_back(v);
    }
  }
  ar = nextar;
}
int computainternos(int u) {
  vector<int> &ar = g[u];
  if (int(ar.size()) == 0) return 0;
  internos[u] = 1;
  for (int i = 0; i < int(ar.size()); i++)
    internos[u] += computainternos(ar[i]);
  return internos[u];
}
int cierra(int u, int p, int l) {
  if (visto[u]) return level[u];
  visto[u] = 1;
  level[u] = l;
  vector<int> &ar = g[u];
  for (int i = 0; i < int(ar.size()); i++) {
    int v = ar[i];
    if (v != p) {
      int lret = cierra(v, u, l + 1);
      if (l < lret) puente[u][v] = puente[v][u] = 1;
      level[u] = min(level[u], lret);
    }
  }
  return level[u];
}
int main() {
  cin >> n >> m;
  vector<pair<int, int> > arista;
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
    arista.push_back(pair<int, int>(u, v));
  }
  for (int u = 1; u <= n; u++) cierra(u, 0, 0);
  for (int i = 0; i < int(arista.size()); i++) {
    pair<int, int> &a = arista[i];
    int u = a.first;
    int v = a.second;
    if (not puente[u][v]) fusion(u, v);
  }
  int costeelim = 0;
  for (int u = 1; u <= n; u++) {
    g[u] = vector<int>();
    if (u != computapadre(u)) {
      eliminado[u] = 1;
      costeelim++;
    }
  }
  for (int i = 0; i < int(arista.size()); i++) {
    pair<int, int> &a = arista[i];
    int u = a.first;
    int v = a.second;
    if (puente[u][v]) {
      u = computapadre(u);
      v = computapadre(v);
      g[u].push_back(v);
      g[v].push_back(u);
    }
  }
  for (int u = 1; u <= n; u++) visto[u] = 0;
  int componentes = 0;
  int coste = 0;
  for (int u = 1; u <= n; u++) {
    if (not eliminado[u] and not visto[u]) {
      componentes++;
      eliminapadre(u, 0);
      computainternos(u);
      coste += computacoste(u);
    }
  }
  cout << coste + componentes - 1 + costeelim << endl;
}
