# Original solution
# 頂点と辺の数を入力する
N, M = list(map(int, input().split()))
# 隣接リストを作成する
list_adjlist = [[] for _ in range(N + 1)]
# 辺のリストを作成する
list_edge = []
# 辺を入力し、隣接リストおよび辺のリストに格納する
for _ in range(M):
    a, b = list(map(int, input().split()))
    list_edge.append((a, b))
    list_adjlist[a].append(b)
    list_adjlist[b].append(a)
    
# 橋の数bridgeを設定する
bridge = 0

# aとbを結ぶ辺について、その辺を通らずにaからbにたどり着けるかを調べる
for a, b in list_edge:
    # これから訪問する頂点のリストlist_nodeを初期化する
    list_node = list_adjlist[a].copy()
    list_node.remove(b)
    # これまでに訪問した頂点の集合set_visit_nodeを初期化する
    set_visit_node = {a}
    # 繰り返し
    while True:
        # 次に訪問可能な頂点の集合set_next_nodeを設定する
        set_next_node = set()
        # list_node内の頂点vに訪問する
        for v in list(list_node):
            # vと隣接している頂点をset_next_nodeに格納する
            set_next_node |= set(list_adjlist[v])
        # set_visit_nodeを更新する
        set_visit_node |= set(list_node)
        # set_next_nodeの全要素がset_visit_nodeに含まれる場合、、
        if set_next_node.issubset(set_visit_node):
            break
        # set_next_nodeの要素にset_visit_nodeに含まれない要素が存在する場合、、
        else:
            # list_nodeを更新する
            list_node = list(set_next_node - set_visit_node)
    # set_visit_nodeにbが含まれない場合（＝aからbにたどり着けない場合）
    if b not in set_visit_node:
        bridge += 1

# 結果を出力する
print(bridge)

# Optimized solution
#幅優先探索（BFS）を利用
# 頂点と辺の数を入力する
N, M = list(map(int, input().split()))
# 隣接リストを作成する
list_adjlist = [[] for _ in range(N + 1)]
# 辺のリストを作成する
list_edge = []
# 辺を入力し、隣接リストおよび辺のリストに格納する
for _ in range(M):
    a, b = list(map(int, input().split()))
    list_edge.append((a, b))
    list_adjlist[a].append(b)
    list_adjlist[b].append(a)

def FIFO(list_FIFO, node):
    if node != None:
        list_FIFO.append(node)
        return None
    return list_FIFO.pop(0)

# 橋の総数（all_bridge）を初期化する
all_bridge = 0

# uv間の辺がなくても、uからvへたどり着けるか探索
for u, v in list_edge:
    # uv間の辺が橋かどうか（uv_bridge）を初期化する（初期状態：1＝橋である）
    uv_bridge = 1
    # FIFOキューを初期化する
    list_FIFO = []
    # FIFOキューに入れたことのある点かどうかをチェックするリスト（list_check）を初期化する
    list_check = [False] * (N + 1)
    # FIFOキューにuを追加する
    FIFO(list_FIFO, u)
    # uをFIFOキューに入れた点としてチェックする
    list_check[u] = True
    # FIFOキューが空でない、かつvにたどり着いていない限り、幅優先探索
    while list_FIFO != [] and list_FIFO[-1] != v:
        # FIFOキューから点（node）を取り出す
        node = FIFO(list_FIFO, None)
        # nodeの隣接点（adjnode）について繰り返す
        for adjnode in list_adjlist[node]:
            # adjnodeがFIFOキューに入れたことのある点だった場合
            if list_check[adjnode]:
                # 以降の処理は行わずに次の隣接点に移る
                continue
            # adjnodeがvだった場合
            if adjnode == v:
                # nodeがuでない場合
                if node != u:  
                    # uv_bridgeを更新する（0＝橋でない）
                    uv_bridge = 0
                    # FIFOキューにadjnodeを追加する
                    FIFO(list_FIFO, adjnode)
                    # 繰り返しを終了する
                    break
            # adjnodeがv出ない場合
            else:
                # FIFOキューにadjnodeを追加する
                FIFO(list_FIFO, adjnode)
                # adjnodeをFIFOキューに入れた点としてチェックする
                list_check[adjnode] = True
    # all_bridgeにuv_bridgeを加える
    all_bridge += uv_bridge
                
# all_bridgeを出力する
print(all_bridge)