#include <bits/stdc++.h>
using namespace std;
const int maxn = 2010;
const int INF = maxn * 100;
const int maxm = 200100;
int n, m;
bool vis[maxn];
bool f[maxn][maxn];
int dfn[maxn], low[maxn], dfs_clock, belong[maxn], cnt = 0, size[maxn];
int S[maxn], top = -1;
int ans = 0, res, node;
struct Graph {
  int first[maxn], to[maxm], edge, _next[maxm];
  Graph() {
    memset(first, -1, sizeof(first));
    edge = 0;
  }
  void add(int a, int b) {
    _next[edge] = first[a];
    to[edge] = b;
    first[a] = edge++;
  }
} G, T;
void dfs(int x, int fa) {
  dfn[x] = low[x] = ++dfs_clock;
  S[++top] = x;
  int v;
  for (int e = G.first[x]; e != -1; e = G._next[e]) {
    v = G.to[e];
    if (v == fa) continue;
    if (!dfn[v]) {
      dfs(v, x);
      low[x] = min(low[x], low[v]);
      if (low[v] == dfn[v]) {
        static int u;
        cnt++;
        size[cnt] = 0;
        while (S[top] != v) {
          u = S[top--];
          belong[u] = cnt;
          size[cnt]++;
        }
        u = S[top--];
        belong[u] = cnt;
        size[cnt]++;
      }
    } else
      low[x] = min(low[x], dfn[v]);
  }
}
int dp[maxn][2], leave;
void Treedp(int x, int fa) {
  vis[x] = 1;
  node++;
  int v, son = 0;
  dp[x][0] = -INF;
  dp[x][1] = -INF;
  for (int e = T.first[x]; e != -1; e = T._next[e]) {
    v = T.to[e];
    if (v == fa) continue;
    son++;
    Treedp(v, x);
    if (dp[v][0] + 1 >= dp[x][0]) {
      dp[x][1] = dp[x][0];
      dp[x][0] = dp[v][0] + 1;
    } else if (dp[v][0] + 1 > dp[x][1])
      dp[x][1] = dp[v][0] + 1;
  }
  if (dp[x][0] == -INF) dp[x][0] = 1;
  if (x == fa && son <= 1) leave++;
  if (x != fa && son == 0) leave++;
  res = max(res, max(dp[x][0], dp[x][0] + dp[x][1] - 1));
}
int main() {
  int a, b;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++) {
    scanf("%d%d", &a, &b);
    if (a == b) continue;
    G.add(a, b);
    G.add(b, a);
  }
  for (int i = 1; i <= n; i++)
    if (!dfn[i]) {
      dfs(i, i);
      if (top >= 0) {
        cnt++;
        size[cnt] = 0;
        while (top >= 0) {
          size[cnt]++;
          belong[S[top--]] = cnt;
        }
      }
    }
  for (int i = 1; i <= cnt; i++) {
    f[i][i] = 1, ans += size[i] - 1;
  }
  for (int i = 1; i <= n; i++) {
    for (int e = G.first[i]; e != -1; e = G._next[e]) {
      if (!f[belong[i]][belong[G.to[e]]]) {
        T.add(belong[i], belong[G.to[e]]);
        T.add(belong[G.to[e]], belong[i]);
        f[belong[i]][belong[G.to[e]]] = f[belong[G.to[e]]][belong[i]] = 1;
      }
    }
  }
  int kuai = 0;
  for (int i = 1; i <= cnt; i++)
    if (!vis[i]) {
      res = -INF;
      leave = 0;
      node = 0;
      Treedp(i, i);
      ans += node - res - leave + ((res == 1) ? 1 : 2);
      kuai++;
    }
  ans += kuai - 1;
  printf("%d\n", ans);
  return 0;
}
