N,M = list(map(int,input().split()))

graph = [[0]*N for _ in range(N)]

Edge = []



for i in range(M):

  a,b = list(map(int,input().split()))

  graph[a-1][b-1] = 1

  graph[b-1][a-1] = 1

  Edge.append([a-1,b-1])



def dfs(x):

  if(vis[x] == 1): return

  vis[x] = 1

  for i in range(N):

    if(graph[x][i] == 1):

      dfs(i)



ans = 0      

for i in range(M):

  graph[Edge[i][0]][Edge[i][1]] = 0

  graph[Edge[i][1]][Edge[i][0]] = 0

  vis = [0]*60

  dfs(0)

  for j in range(N):

    if(vis[j] == 0):

      ans += 1

      break

  graph[Edge[i][0]][Edge[i][1]] = 1

  graph[Edge[i][1]][Edge[i][0]] = 1

print(ans)
class UnionFind():

    # 作りたい要素数nで初期化

    # 使用するインスタンス変数の初期化

    def __init__(self, n):

        self.n = n

        # root[x]<0ならそのノードが根かつその値が木の要素数

        # rootノードでその木の要素数を記録する

        self.root = [-1]*(n+1)

        # 木をくっつける時にアンバランスにならないように調整する

        self.rnk = [0]*(n+1)



    # ノードxのrootノードを見つける

    def Find_Root(self, x):

        if(self.root[x] < 0):

            return x

        else:

            # ここで代入しておくことで、後の繰り返しを避ける

            self.root[x] = self.Find_Root(self.root[x])

            return self.root[x]

    # 木の併合、入力は併合したい各ノード

    def Unite(self, x, y):

        # 入力ノードのrootノードを見つける

        x = self.Find_Root(x)

        y = self.Find_Root(y)

        # すでに同じ木に属していた場合

        if(x == y):

            return 

        # 違う木に属していた場合rnkを見てくっつける方を決める

        elif(self.rnk[x] > self.rnk[y]):

            self.root[x] += self.root[y]

            self.root[y] = x



        else:

            self.root[y] += self.root[x]

            self.root[x] = y

            # rnkが同じ（深さに差がない場合）は1増やす

            if(self.rnk[x] == self.rnk[y]):

                self.rnk[y] += 1

    # xとyが同じグループに属するか判断

    def isSameGroup(self, x, y):

        return self.Find_Root(x) == self.Find_Root(y)



    # ノードxが属する木のサイズを返す

    def Count(self, x):

        return -self.root[self.Find_Root(x)]

      

N,M = list(map(int,input().split()))

Edge = []

for i in range(M):

  a,b = list(map(int,input().split()))

  Edge.append([a-1,b-1])



ans = 0

for i in range(M):

 graph = UnionFind(N)

 for j in range(M):

   if(i != j): 

    graph.Unite(Edge[j][0],Edge[j][1])

 if(graph.Count(0) != N): ans += 1

print(ans)
N, M = list(map(int, input().split()))
graph = [[0] * N for _ in range(N)]
Edge = []
for i in range(M):
    a, b = list(map(int, input().split()))
    graph[a - 1][b - 1] = 1
    graph[b - 1][a - 1] = 1
    Edge.append([a - 1, b - 1])


def dfs(x):
    if vis[x] == 1:
        return
    vis[x] = 1
    for i in range(N):
        if graph[x][i] == 1:
            dfs(i)


ans = 0
for i in range(M):
    graph[Edge[i][0]][Edge[i][1]] = 0
    graph[Edge[i][1]][Edge[i][0]] = 0
    vis = [0] * 60
    dfs(0)
    for j in range(N):
        if vis[j] == 0:
            ans += 1
            break
    graph[Edge[i][0]][Edge[i][1]] = 1
    graph[Edge[i][1]][Edge[i][0]] = 1
print(ans)

class UnionFind:
    # 作りたい要素数nで初期化
    # 使用するインスタンス変数の初期化
    def __init__(self, n):
        self.n = n
        # root[x]<0ならそのノードが根かつその値が木の要素数
        # rootノードでその木の要素数を記録する
        self.root = [-1] * (n + 1)
        # 木をくっつける時にアンバランスにならないように調整する
        self.rnk = [0] * (n + 1)

    # ノードxのrootノードを見つける
    def Find_Root(self, x):
        if self.root[x] < 0:
            return x
        else:
            # ここで代入しておくことで、後の繰り返しを避ける
            self.root[x] = self.Find_Root(self.root[x])
            return self.root[x]

    # 木の併合、入力は併合したい各ノード
    def Unite(self, x, y):
        # 入力ノードのrootノードを見つける
        x = self.Find_Root(x)
        y = self.Find_Root(y)
        # すでに同じ木に属していた場合
        if x == y:
            return
        # 違う木に属していた場合rnkを見てくっつける方を決める
        elif self.rnk[x] > self.rnk[y]:
            self.root[x] += self.root[y]
            self.root[y] = x
        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            # rnkが同じ（深さに差がない場合）は1増やす
            if self.rnk[x] == self.rnk[y]:
                self.rnk[y] += 1

    # xとyが同じグループに属するか判断
    def isSameGroup(self, x, y):
        return self.Find_Root(x) == self.Find_Root(y)

    # ノードxが属する木のサイズを返す
    def Count(self, x):
        return -self.root[self.Find_Root(x)]


N, M = list(map(int, input().split()))
Edge = []
for i in range(M):
    a, b = list(map(int, input().split()))
    Edge.append([a - 1, b - 1])
ans = 0
for i in range(M):
    graph = UnionFind(N)
    for j in range(M):
        if i != j:
            graph.Unite(Edge[j][0], Edge[j][1])
    if graph.Count(0) != N:
        ans += 1
print(ans)

+class UnionFind: +    # 作りたい要素数nで初期化 +    # 使用するインスタンス変数の初期化 +    def __init__(self, n): +        self.n = n +        # root[x]<0ならそのノードが根かつその値が木の要素数 +        # rootノードでその木の要素数を記録する +        self.root = [-1] * (n + 1) +        # 木をくっつける時にアンバランスにならないように調整する +        self.rnk = [0] * (n + 1) + +    # ノードxのrootノードを見つける +    def Find_Root(self, x): +        if self.root[x] < 0: +            return x +        else: +            # ここで代入しておくことで、後の繰り返しを避ける +            self.root[x] = self.Find_Root(self.root[x]) +            return self.root[x] + +    # 木の併合、入力は併合したい各ノード +    def Unite(self, x, y): +        # 入力ノードのrootノードを見つける +        x = self.Find_Root(x) +        y = self.Find_Root(y) +        # すでに同じ木に属していた場合 +        if x == y: +            return +        # 違う木に属していた場合rnkを見てくっつける方を決める +        elif self.rnk[x] > self.rnk[y]: +            self.root[x] += self.root[y] +            self.root[y] = x +        else: +            self.root[y] += self.root[x] +            self.root[x] = y +            # rnkが同じ（深さに差がない場合）は1増やす +            if self.rnk[x] == self.rnk[y]: +                self.rnk[y] += 1 + +    # xとyが同じグループに属するか判断 +    def isSameGroup(self, x, y): +        return self.Find_Root(x) == self.Find_Root(y) + +    # ノードxが属する木のサイズを返す +    def Count(self, x): +        return -self.root[self.Find_Root(x)] + + -graph = [[0] * N for _ in range(N)] -    graph[a - 1][b - 1] = 1 -    graph[b - 1][a - 1] = 1 - - -def dfs(x): -    if vis[x] == 1: -        return -    vis[x] = 1 -    for i in range(N): -        if graph[x][i] == 1: -            dfs(i) - - -    graph[Edge[i][0]][Edge[i][1]] = 0 -    graph[Edge[i][1]][Edge[i][0]] = 0 -    vis = [0] * 60 -    dfs(0) -    for j in range(N): -        if vis[j] == 0: -            ans += 1 -            break -    graph[Edge[i][0]][Edge[i][1]] = 1 -    graph[Edge[i][1]][Edge[i][0]] = 1 +    graph = UnionFind(N) +    for j in range(M): +        if i != j: +            graph.Unite(Edge[j][0], Edge[j][1]) +    if graph.Count(0) != N: +        ans += 1