# 全部試す

# 1つあたりO(M)

# O(M^2) = 10^6くらい

import numpy as np

from scipy.sparse.csgraph import dijkstra



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

edge = [list(map(int, input().split())) for _ in range(M)]



graph = np.zeros((N+1, N+1))



for a, b in edge:

  graph[a, b] = 1

  

ans = 0

for a, b in edge:

  graph[a, b] = np.inf 

  # directed=False -> 無向グラフ

  dist = dijkstra(graph, indices=a, directed=False)

  if dist[b] == np.inf:

    ans += 1

  graph[a, b] = 1 # 元に戻す

  

print(ans)  
class UnionFind():

    def __init__(self, N):

        """ N個のノードのUnion-Find木を作成する """

        # 親の番号を格納する。自分が親だった場合は、自分の番号になり、それがそのグループの番号になる

        self.parent = [n for n in range(0, N)]

        # グループの深さ

        self.depth = [1] * N

 

    def find(self, x):

        """ 木の根(どのグループか)を求める """

        if self.parent[x] == x: return x

        self.parent[x] = self.find(self.parent[x]) # 縮約

        return self.parent[x]

 

    def unite(self, x, y):

        """ xとyの属する集合を併合する """

        gx = self.find(x)

        gy = self.find(y)

        if gx == gy: return

 

        # 小さい方を大きい方に併合させる（木の偏りが減るので）

        if self.depth[gx] < self.depth[gy]:

            self.parent[gx] = gy

        else:

            self.parent[gy] = gx

            if self.depth[gx] == self.depth[gy]: self.depth[gx] += 1

 

    def is_same_group(self, x, y):

        """ xとyが同じ集合に属するか否か """

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

      

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

E = [[int(x)-1 for x in input().split()] for _ in range(M)]



# 各辺について、その辺が存在しない時、aとbが連結になるかをUnion-Findで判定する

ans = 0

for i in range(M):

  uf = UnionFind(N)

  for j, e in enumerate(E):

    if i==j: continue

        

    a, b = e

    uf.unite(a, b)

      

  # i番目の辺を除くすべての辺をつないだあとで、i番目の辺(a, b)がつながるかを判定する

  # つながらないならば、そのi番目の辺は橋である

  a, b = E[i]

  if not uf.is_same_group(a, b):

    ans += 1



print(ans)      

# 全部試す
# 1つあたりO(M)
# O(M^2) = 10^6くらい
import numpy as np
from scipy.sparse.csgraph import dijkstra

N, M = list(map(int, input().split()))
edge = [list(map(int, input().split())) for _ in range(M)]
graph = np.zeros((N + 1, N + 1))
for a, b in edge:
    graph[a, b] = 1
ans = 0
for a, b in edge:
    graph[a, b] = np.inf
    # directed=False -> 無向グラフ
    dist = dijkstra(graph, indices=a, directed=False)
    if dist[b] == np.inf:
        ans += 1
    graph[a, b] = 1  # 元に戻す
print(ans)

class UnionFind:
    def __init__(self, N):
        """N個のノードのUnion-Find木を作成する"""
        # 親の番号を格納する。自分が親だった場合は、自分の番号になり、それがそのグループの番号になる
        self.parent = [n for n in range(0, N)]
        # グループの深さ
        self.depth = [1] * N

    def find(self, x):
        """木の根(どのグループか)を求める"""
        if self.parent[x] == x:
            return x
        self.parent[x] = self.find(self.parent[x])  # 縮約
        return self.parent[x]

    def unite(self, x, y):
        """xとyの属する集合を併合する"""
        gx = self.find(x)
        gy = self.find(y)
        if gx == gy:
            return
        # 小さい方を大きい方に併合させる（木の偏りが減るので）
        if self.depth[gx] < self.depth[gy]:
            self.parent[gx] = gy
        else:
            self.parent[gy] = gx
            if self.depth[gx] == self.depth[gy]:
                self.depth[gx] += 1

    def is_same_group(self, x, y):
        """xとyが同じ集合に属するか否か"""
        return self.find(x) == self.find(y)


N, M = list(map(int, input().split()))
E = [[int(x) - 1 for x in input().split()] for _ in range(M)]
# 各辺について、その辺が存在しない時、aとbが連結になるかをUnion-Findで判定する
ans = 0
for i in range(M):
    uf = UnionFind(N)
    for j, e in enumerate(E):
        if i == j:
            continue
        a, b = e
        uf.unite(a, b)
    # i番目の辺を除くすべての辺をつないだあとで、i番目の辺(a, b)がつながるかを判定する
    # つながらないならば、そのi番目の辺は橋である
    a, b = E[i]
    if not uf.is_same_group(a, b):
        ans += 1
print(ans)

-# 全部試す -# 1つあたりO(M) -# O(M^2) = 10^6くらい -import numpy as np -from scipy.sparse.csgraph import dijkstra +class UnionFind: +    def __init__(self, N): +        """N個のノードのUnion-Find木を作成する""" +        # 親の番号を格納する。自分が親だった場合は、自分の番号になり、それがそのグループの番号になる +        self.parent = [n for n in range(0, N)] +        # グループの深さ +        self.depth = [1] * N + +    def find(self, x): +        """木の根(どのグループか)を求める""" +        if self.parent[x] == x: +            return x +        self.parent[x] = self.find(self.parent[x])  # 縮約 +        return self.parent[x] + +    def unite(self, x, y): +        """xとyの属する集合を併合する""" +        gx = self.find(x) +        gy = self.find(y) +        if gx == gy: +            return +        # 小さい方を大きい方に併合させる（木の偏りが減るので） +        if self.depth[gx] < self.depth[gy]: +            self.parent[gx] = gy +        else: +            self.parent[gy] = gx +            if self.depth[gx] == self.depth[gy]: +                self.depth[gx] += 1 + +    def is_same_group(self, x, y): +        """xとyが同じ集合に属するか否か""" +        return self.find(x) == self.find(y) + -edge = [list(map(int, input().split())) for _ in range(M)] -graph = np.zeros((N + 1, N + 1)) -for a, b in edge: -    graph[a, b] = 1 +E = [[int(x) - 1 for x in input().split()] for _ in range(M)] +# 各辺について、その辺が存在しない時、aとbが連結になるかをUnion-Findで判定する -for a, b in edge: -    graph[a, b] = np.inf -    # directed=False -> 無向グラフ -    dist = dijkstra(graph, indices=a, directed=False) -    if dist[b] == np.inf: +for i in range(M): +    uf = UnionFind(N) +    for j, e in enumerate(E): +        if i == j: +            continue +        a, b = e +        uf.unite(a, b) +    # i番目の辺を除くすべての辺をつないだあとで、i番目の辺(a, b)がつながるかを判定する +    # つながらないならば、そのi番目の辺は橋である +    a, b = E[i] +    if not uf.is_same_group(a, b): -    graph[a, b] = 1  # 元に戻す