# C

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

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

visited = [False]*N



def dfs(cur):

    global visited

    visited[cur] = True

    for nxt in range(N):

        if graph[cur][nxt]==False: continue

        if visited[nxt]==True: continue

        dfs(nxt)





a = [-1]*M

b = [-1]*M

for i in range(M):

    ai,bi = list(map(int, input().split()))

    a[i],b[i] = ai-1, bi-1

    graph[a[i]][b[i]] = True

    graph[b[i]][a[i]] = True



ans = 0

for i in range(M):

    graph[a[i]][b[i]] = False # 辺を消す

    graph[b[i]][a[i]] = False

    # print("graph: "+"\n".join(map(str, graph)))

    visited = [False]*N

    dfs(0)

    if not all(visited):

        ans += 1

    graph[a[i]][b[i]] = True # 辺を戻す

    graph[b[i]][a[i]] = True

    

print(ans)
class UnionFind:

    """

    - sizeを指定

    - 要素をグループにまとめる(unite) 

    - 要素同士が同じグループか判定する(isSame)

    - 分離はできない

    - par: 親の番号(はじめ par[i]==i つまりすべての頂点が根)

     - 始め各要素は別々のグループ"""

    def __init__(self, size: int):

        self.par = [-1]*size

        for i in range(size):

            self.par[i] = i 

    

    def root(self, x: int) -> int:

        """根を求める"""

        if self.par[x] == x: # if root

            return x

        else:

            self.par[x] = self.root(self.par[x]) # 経路圧縮

            return self.par[x]

    

    def isSame(self, x:int, y:int)->bool:

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

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

    

    def unite(self, x:int, y:int):

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

        x = self.root(x)

        y = self.root(y)

        if x == y: return

        self.par[x] = y



        

        

##### main #####

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

a,b = [0]*M, [0]*M

for i in range(M):

    ai,bi = list(map(int, input().split()))

    a[i],b[i] = ai-1, bi-1

    

ans = 0

for i in range(M):

    uf = UnionFind(N)

    for j in range(M):

        if i==j: continue # この辺はパス

        uf.unite(a[j], b[j])

    bridge = False

    for i in range(N):

        if not uf.isSame(0,i):

            bridge = True

    if bridge:

        ans += 1

print(ans)
# C
N, M = list(map(int, input().split()))
graph = [[False] * N for _ in range(N)]
visited = [False] * N


def dfs(cur):
    global visited
    visited[cur] = True
    for nxt in range(N):
        if graph[cur][nxt] == False:
            continue
        if visited[nxt] == True:
            continue
        dfs(nxt)


a = [-1] * M
b = [-1] * M
for i in range(M):
    ai, bi = list(map(int, input().split()))
    a[i], b[i] = ai - 1, bi - 1
    graph[a[i]][b[i]] = True
    graph[b[i]][a[i]] = True
ans = 0
for i in range(M):
    graph[a[i]][b[i]] = False  # 辺を消す
    graph[b[i]][a[i]] = False
    # print("graph: "+"\n".join(map(str, graph)))
    visited = [False] * N
    dfs(0)
    if not all(visited):
        ans += 1
    graph[a[i]][b[i]] = True  # 辺を戻す
    graph[b[i]][a[i]] = True
print(ans)

class UnionFind:
    """
    - sizeを指定
    - 要素をグループにまとめる(unite)
    - 要素同士が同じグループか判定する(isSame)
    - 分離はできない
    - par: 親の番号(はじめ par[i]==i つまりすべての頂点が根)
     - 始め各要素は別々のグループ"""

    def __init__(self, size: int):
        self.par = [-1] * size
        for i in range(size):
            self.par[i] = i

    def root(self, x: int) -> int:
        """根を求める"""
        if self.par[x] == x:  # if root
            return x
        else:
            self.par[x] = self.root(self.par[x])  # 経路圧縮
            return self.par[x]

    def isSame(self, x: int, y: int) -> bool:
        """x と y が同じ集合に属するか否か"""
        return self.root(x) == self.root(y)

    def unite(self, x: int, y: int):
        """x と y の属する集合を併合"""
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return
        self.par[x] = y


##### main #####
N, M = list(map(int, input().split()))
a, b = [0] * M, [0] * M
for i in range(M):
    ai, bi = list(map(int, input().split()))
    a[i], b[i] = ai - 1, bi - 1
ans = 0
for i in range(M):
    uf = UnionFind(N)
    for j in range(M):
        if i == j:
            continue  # この辺はパス
        uf.unite(a[j], b[j])
    bridge = False
    for i in range(N):
        if not uf.isSame(0, i):
            bridge = True
    if bridge:
        ans += 1
print(ans)

-# C -N, M = list(map(int, input().split())) -graph = [[False] * N for _ in range(N)] -visited = [False] * N +class UnionFind: +    """ +    - sizeを指定 +    - 要素をグループにまとめる(unite) +    - 要素同士が同じグループか判定する(isSame) +    - 分離はできない +    - par: 親の番号(はじめ par[i]==i つまりすべての頂点が根) +     - 始め各要素は別々のグループ""" + +    def __init__(self, size: int): +        self.par = [-1] * size +        for i in range(size): +            self.par[i] = i + +    def root(self, x: int) -> int: +        """根を求める""" +        if self.par[x] == x:  # if root +            return x +        else: +            self.par[x] = self.root(self.par[x])  # 経路圧縮 +            return self.par[x] + +    def isSame(self, x: int, y: int) -> bool: +        """x と y が同じ集合に属するか否か""" +        return self.root(x) == self.root(y) + +    def unite(self, x: int, y: int): +        """x と y の属する集合を併合""" +        x = self.root(x) +        y = self.root(y) +        if x == y: +            return +        self.par[x] = y -def dfs(cur): -    global visited -    visited[cur] = True -    for nxt in range(N): -        if graph[cur][nxt] == False: -            continue -        if visited[nxt] == True: -            continue -        dfs(nxt) - - -a = [-1] * M -b = [-1] * M +##### main ##### +N, M = list(map(int, input().split())) +a, b = [0] * M, [0] * M -    graph[a[i]][b[i]] = True -    graph[b[i]][a[i]] = True -    graph[a[i]][b[i]] = False  # 辺を消す -    graph[b[i]][a[i]] = False -    # print("graph: "+"\n".join(map(str, graph))) -    visited = [False] * N -    dfs(0) -    if not all(visited): +    uf = UnionFind(N) +    for j in range(M): +        if i == j: +            continue  # この辺はパス +        uf.unite(a[j], b[j]) +    bridge = False +    for i in range(N): +        if not uf.isSame(0, i): +            bridge = True +    if bridge: -    graph[a[i]][b[i]] = True  # 辺を戻す -    graph[b[i]][a[i]] = True