class UnionFind
    def initialize(n) # 必要な配列を設定、nはノード(頂点)の数
        @rank = Array.new(n,0) # 端っこからたどって何番目の階層かを記録、大きいほうが親となる
        @parent = Array.new(n,&:itself) #初期設定では自分の親は自分の番号と同じ
    end
    def get_parent(id_x) # 根(親)を表示する関数
        @parent[id_x] = get_parent(@parent[id_x]) if id_x != @parent[id_x]
        return @parent[id_x]
    end
    def same_parent?(id_x, id_y) # ２つのノードid_x、id_yが連結しているかどうかを調べる
        get_parent(id_x) == get_parent(id_y)
        # if same_parent?(x,y)のように使う、同じ親ならtrue、別であればfalse
    end
    def unite(id_x, id_y) # ２つのノードid_x、id_yをつなげる
        x_parent = get_parent(id_x) # id_xの親
        y_parent = get_parent(id_y) # 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が大親になっている
          @rank[y_parent] += 1 if @rank[x_parent] == @rank[y_parent]
          # rankが同じ場合は仕方なく後者を親にしてrankを一つ増やす、これで一行上の操作は正当化される
        end
    end
    def tree_size(id_x) # id_xが存在するツリーに存在するノードの数
        return @parent.count(@parent[id_x])
    end
    def group_size() # 全体の独立した集合の数、すなわち互いに素な集合の個数
        return @parent.uniq.size
    end
    def look_parent() # 配列@parentを表示する
        return @parent
    end
    def look_rank() # 配列@rankを表示する
        return @rank
    end
end

n,m = gets.strip.split.map(&:to_i)
uf = UnionFind.new(n)
m.times do
  a,b = gets.strip.split.map(&:to_i)
  uf.unite(a-1, b-1)
end
p uf.group_size()-1