# Union-Find木
# 木構造を用いて、グループ分けを行うデータ構造
# 同じ木に属している場合、同じグループであるということになる
# 同じ木に属しているかどうかは、根となるノードが同じであるかどうかで判定をする
# 同じグループに属しているかどうかを、根ノードの値を参照するだけなのでO(1)で求められる
class UnionFind
  def initialize(size)
    @rank = Array.new(size, 0)
    @parent = Array.new(size, &:itself)
  end

  def tmp(n)
    arr = Array.new(n, 0)
    @parent.each do |num|
      arr[num] += 1
    end
    return arr.max
  end

  # node_xとnode_yを連結し、同じグループにする
  def unite(id_x, id_y)
    x_parent = get_parent(id_x)
    y_parent = get_parent(id_y)
    return if x_parent == y_parent

    if @rank[x_parent] > @rank[y_parent]
      @parent[y_parent] = x_parent
    else
      @parent[x_parent] = y_parent
      @rank[y_parent] += 1 if @rank[x_parent] == @rank[y_parent]
    end
  end

  # node_xの親ノードの番号を取得する
  def get_parent(id_x)
    @parent[id_x] == id_x ? id_x : (@parent[id_x] = get_parent(@parent[id_x]))
  end

  # node_x, node_yが連結しているか確かめる
  def same_parent?(id_x, id_y)
    get_parent(id_x) == get_parent(id_y)
  end
end

def input_n
  gets.to_i               # 単一整数
end

def input_s
  gets.chomp              # 文字列。chompを付けないと改行文字がついてくる
end

def input_a
  gets.split.map(&:to_i)  # スペースで区切られた複数の整数
end

def input_o(num)
  num.times.map { gets.to_i }  # 縦に並んだ複数の整数。たまにある
end

def output_f(num)
  puts sprintf("%.12f", num)
end

n, m = input_a
# 与えられた頂点数の大きさで宣言を行う
union = UnionFind.new(n + 1)

# ノード読み込み
a, b = m.times.map { gets.split.map(&:to_i) }.transpose
#p a
#p b
(m).times do |i|
  # 結合処理
  #  puts "#{i} #{a[i]} #{b[i]}"
  union.unite(a[i], b[i])
end

cnt = 0
(m).times do |i|
  # 判定処理
  if union.same_parent?(a[i], b[i])
    cnt += 1
  end
end
p union.tmp(n + 1)
