#include "bits/stdc++.h" // {{{
using namespace std; typedef long long ll; typedef pair<int,int> pii;
#define val         const auto
#define eb          emplace_back
#define emp         emplace
#define fi          first
#define se          second
#define outl(x)     cout << (x) << '\n'
#define rep(i,n)    for(int i=0; i < (int)(n); ++i)
#define repr(i,h,l) for(int i=(h); i >= (int)(l); --i)
#define reps(i,s,t) for(int i=(s); i <= (int)(t); ++i)
#define ALL(x)      begin(x), end(x)
#define UNQ(x)      (x).erase(std::unique(ALL(x)), end(x))
#define TMPLT(T,U)  template<class T, class U>
#define ten(p)      ((long long)(1e##p))
#define FILL(a,v)   memset((a), (v), sizeof(a))
#define YDK(f,a,b)  ((f)? (a):(b))
#ifdef  DEBUG
#define debug(...)  fprintf(stderr, __VA_ARGS__)
#define show(x)     clog << #x << " \t\t= " << (x) << '\n'
#define show2(x,y)  clog << '(' << #x << ',' << #y << ")\t\t= " << '(' << (x) << "\t, " << (y) << ")\n"
#define LN()        fputs("\n--------------------------------\n", stderr)
struct NullPointer{};
#else
#define debug(...)
#define show(x)
#define show2(x,y)
#define LN()
struct NullPointer{ NullPointer(){cin.tie(0);ios::sync_with_stdio(false);} };
#endif
#define def(op) inline bool operator op (const T &that) const { return comp(that) op 0; }
template<class T> struct Ordered
{ virtual int comp(const T &that) const = 0; def(==); def(!=); def(<); def(<=); def(>); def(>=); };
#undef def
namespace {
  constexpr int INF = 0x3f3f3f3f; constexpr ll LINF = 0x3f3f3f3f3f3f3f3fLL; ostringstream _oss;
  TMPLT(T,U) inline constexpr common_type_t<T,U> gcd(T x, U y)
  { return (x<y)? gcd(y,x) : (y <= 0)? x : gcd(y, x % y); }
  TMPLT(T,U) inline bool chmax(T &a, const U &b){return b>a ? a=b,1 : 0;}
  TMPLT(T,U) inline bool chmin(T &a, const U &b){return b<a ? a=b,1 : 0;}
  TMPLT(T,U) inline constexpr ll lcm(T x, U y) { return (ll)x/gcd(x,y) * y; }
  template<class T>   string toString(const T &x){ _oss.str(""); _oss << x; return _oss.str(); }
  template<class Itr> string mkString(Itr begin, Itr end, const char *sp = " ") {
    _oss.str(""); for(Itr i=begin; i != end; ++i) { if(i != begin)_oss << sp; _oss << *i; }
    return _oss.str();
  }
  // }}}

constexpr int MX = ten(5) + 10;

int N, M;
bool G[55][55];

struct UnionFind {
  vector<int> uni;
  UnionFind(int n): uni(n+5, -1) {}
  int  root(int x)        { return (uni[x] < 0)? x : uni[x] = root(uni[x]); }
  bool same(int x, int y) { return root(x) == root(y); }
  bool unite(int x, int y){
    if ( (x=root(x)) == (y=root(y)) )return false;
    if ( uni[y] < uni[x] ) swap(x,y);
    uni[x] += uni[y],  uni[y] = x;
    return true;
  }
  int size(int i)     { return (-uni[root(i)]); }
};

bool notConnected()
{
  UnionFind uf(N);
  for (int s = 0; s < N; ++s) {
    for(int t = s+1; t < N; ++t) {
      if (G[s][t]) uf.unite(s,t);
    }
  }

  rep(i, N-1) {
    if (!uf.same(i, i+1)) return true;
  }
  return false;
}

void Xx_main_xX(const vector<char*> &args)
{
  cin >> N >>  M;
  rep(i, M) {
    int s, t;
    cin >> s >> t;
    --s, --t;
    G[s][t] = G[t][s] = true;
  }

  int ans = 0;

  for (int s = 0; s < N; ++s) {
    for (int t = s+1; t < N; ++t) {
      if (G[s][t]) {
        G[s][t] = G[t][s] = false;
        if (notConnected()) ++ans;
        G[s][t] = G[t][s] = true;
      }
    }
  }

  outl(ans);
}

} // {{{
signed main(signed argc, char *argv[]) {
  NullPointer Exception;
  cout << fixed << setprecision(9); Xx_main_xX(vector<char*>(argv, argv+argc)); return 0;
} // }}}



Measured memory_bytes: 256