#include <bits/stdc++.h>   using namespace std;   inline int readInt() {     char c;     int tmp = 0, x = 1;     c = getchar();     while (c >  9  || c <  0 ) {       if (c ==  - ) x = -1;       c = getchar();     }     while (c >=  0  && c <=  9 ) {       tmp = tmp * 10 + c -  0 ;       c = getchar();     }     return tmp * x;   }   const int maxN = 2000 + 10;   const int maxM = 100000 + 10;   int Head[maxN], eg[maxM << 1], nxt[maxM << 1], tot = 1;   void addEdge(int u, int v) {     eg[++tot] = v;     nxt[tot] = Head[u];     Head[u] = tot;     eg[++tot] = u;     nxt[tot] = Head[v];     Head[v] = tot;   }   bool isbri[maxM << 2];   int dfn[maxN], low[maxN], dfsclock = 0;   void tarjan(int v, int InEdge) {     dfn[v] = low[v] = ++dfsclock;     for (int i = Head[v]; i; i = nxt[i]) {       int u = eg[i];       if (!dfn[u]) {         tarjan(u, i);         low[v] = min(low[v], low[u]);         if (low[u] > dfn[v]) isbri[i] = isbri[i ^ 1] = true;       } else if (i != (InEdge ^ 1))         low[v] = min(low[v], dfn[u]);     }   }   int bccno[maxN], num = 0, bccsiz[maxN];   void dfs(int v) {     bccno[v] = num;     bccsiz[num]++;     for (int i = Head[v]; i; i = nxt[i]) {       int u = eg[i];       if (!bccno[u] && !isbri[i]) dfs(u);     }   }   vector<int> g[maxN];   void new_addEdge(int u, int v) {     g[u].push_back(v);     g[v].push_back(u);   }   bool vis[maxN], isLeaf[maxN];   int tmp = 0, tmpmax = -1, tmpleaf = 0, Leaf[maxN], siz[maxN], rot[maxN],       cnt = 0, Fa[maxN], Belong[maxN];   void predfs(int v, int fa) {     siz[v] = 1;     Fa[v] = fa;     Belong[v] = cnt;     if ((int)g[v].size() == 0 || (int)g[v].size() == 1)       Leaf[cnt]++, isLeaf[v] = true;     for (int i = 0; i < (int)g[v].size(); i++) {       int u = g[v][i];       if (u != fa) predfs(u, v), siz[v] += siz[u];     }   }   void FindLongest(int v, int fa, int D, int lev) {     if (tmp < D) tmp = D, tmpmax = v, tmpleaf = lev;     for (int i = 0; i < (int)g[v].size(); i++) {       int u = g[v][i];       if (u != fa) FindLongest(u, v, D + (!isLeaf[u]), lev + isLeaf[u]);     }   }   int FindDiameter(int v) {     tmp = 0, tmpmax = -1;     for (int i = 0; i < (int)g[v].size(); i++) {       int u = g[v][i];       FindLongest(u, v, 1, 0);     }     if (!(~tmpmax)) return 0;     int vv = tmpmax;     tmp = 0, tmpmax = -1, tmpleaf = 0;     FindLongest(vv, -1, 1, isLeaf[vv]);     return tmp - tmpleaf;   }   int n, m;   int main() {     n = readInt(), m = readInt();     int u, v;     for (int i = 1; i <= m; i++) {       u = readInt(), v = readInt();       addEdge(u, v);     }     for (int i = 1; i <= n; i++) {       if (!dfn[i]) tarjan(i, 0);     }     for (int i = 1; i <= n; i++) {       if (!bccno[i]) {         num++;         dfs(i);       }     }     for (int i = 2; i <= tot; i += 2) {       if (bccno[eg[i]] != bccno[eg[i ^ 1]]) {         new_addEdge(bccno[eg[i]], bccno[eg[i ^ 1]]);       }     }     int ans = 0;     for (int i = 1; i <= num; i++) ans += bccsiz[i] - 1;     cnt = 0;     for (int i = 1; i <= num; i++) {       if (!Belong[i]) cnt++, rot[cnt] = i, predfs(i, -1);     }     ans += cnt - 1;     for (int i = 1; i <= cnt; i++) {       int d = FindDiameter(rot[i]);       ans += siz[rot[i]] - d - Leaf[i];     }     printf( %d n , ans);     return 0;   }