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

city=[0]*(N+10)



#都市情報を初期化

for i in range(1,N+1):

  city[i]=i

  

#都市番号の小さい方を根としてUnionFind木を作成(大きい方を書き換える)

for i in range(M):

  A,B=list(map(int,input().split()))

#  print(A,B)



#ルートチェック

  if city[A]!=A:

    root=city[A]

    while city[root]!=root:

      root=city[root]

    city[A]=root

  

  if city[B]!=B:

    root=city[B]

    while city[root]!=root:

      root=city[root]

    city[B]=root



#結合

  if city[A]!=city[B]:

    city[city[B]]=city[A]

    

#print(city)

  

#木が何種類あるかチェック

ck=[0]*(N+10)

for i in range(1,N+1):

  if city[i]!=i:

    root=city[i]

    while city[root]!=root:

      root=city[root]

    city[i]=root

    

  if ck[city[i]]==0:

    ck[city[i]]=1

    

#print(city)

#print(ck)

Ans=sum(ck)-1 #木の数-1=必要な道路数



print(Ans)
class UnionFind():

  def __init__(self, n):

    self.par = [i for i in range(n+1)]

    self.rank = [0] * (n+1)

    

  def find(self, x):

    if self.par[x] == x:

      return x

    else:

      self.par[x] = self.find(self.par[x])

      return self.par[x]



  def unite(self, x, y):

    x = self.find(x)

    y = self.find(y)

    if self.rank[x] < self.rank[y]:

      self.par[x] = y

    else:

      self.par[y] = x

      

    if self.rank[x] == self.rank[y]:

      self.rank[x] += 1



  def same(self, x, y):

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



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

city=UnionFind(N)



for i in range(M):

  A,B=list(map(int,input().split()))

  city.unite(A,B)



ck=[0]*(N+10)

for i in range(1,N+1):

  root=city.find(i)

  if ck[root]==0:

    ck[root]=1

    

#print(city.par)

#print(ck)

    

Ans=sum(ck)-1

print(Ans)

N, M = list(map(int, input().split()))
city = [0] * (N + 10)
# 都市情報を初期化
for i in range(1, N + 1):
    city[i] = i
# 都市番号の小さい方を根としてUnionFind木を作成(大きい方を書き換える)
for i in range(M):
    A, B = list(map(int, input().split()))
    #  print(A,B)
    # ルートチェック
    if city[A] != A:
        root = city[A]
        while city[root] != root:
            root = city[root]
        city[A] = root
    if city[B] != B:
        root = city[B]
        while city[root] != root:
            root = city[root]
        city[B] = root
    # 結合
    if city[A] != city[B]:
        city[city[B]] = city[A]
# print(city)
# 木が何種類あるかチェック
ck = [0] * (N + 10)
for i in range(1, N + 1):
    if city[i] != i:
        root = city[i]
        while city[root] != root:
            root = city[root]
        city[i] = root
    if ck[city[i]] == 0:
        ck[city[i]] = 1
# print(city)
# print(ck)
Ans = sum(ck) - 1  # 木の数-1=必要な道路数
print(Ans)

class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n + 1)]
        self.rank = [0] * (n + 1)

    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
        else:
            self.par[y] = x
        if self.rank[x] == self.rank[y]:
            self.rank[x] += 1

    def same(self, x, y):
        return self.find(x) == self.find(y)


N, M = list(map(int, input().split()))
city = UnionFind(N)
for i in range(M):
    A, B = list(map(int, input().split()))
    city.unite(A, B)
ck = [0] * (N + 10)
for i in range(1, N + 1):
    root = city.find(i)
    if ck[root] == 0:
        ck[root] = 1
# print(city.par)
# print(ck)
Ans = sum(ck) - 1
print(Ans)

+class UnionFind: +    def __init__(self, n): +        self.par = [i for i in range(n + 1)] +        self.rank = [0] * (n + 1) + +    def find(self, x): +        if self.par[x] == x: +            return x +        else: +            self.par[x] = self.find(self.par[x]) +            return self.par[x] + +    def unite(self, x, y): +        x = self.find(x) +        y = self.find(y) +        if self.rank[x] < self.rank[y]: +            self.par[x] = y +        else: +            self.par[y] = x +        if self.rank[x] == self.rank[y]: +            self.rank[x] += 1 + +    def same(self, x, y): +        return self.find(x) == self.find(y) + + -city = [0] * (N + 10) -# 都市情報を初期化 -for i in range(1, N + 1): -    city[i] = i -# 都市番号の小さい方を根としてUnionFind木を作成(大きい方を書き換える) +city = UnionFind(N) -    #  print(A,B) -    # ルートチェック -    if city[A] != A: -        root = city[A] -        while city[root] != root: -            root = city[root] -        city[A] = root -    if city[B] != B: -        root = city[B] -        while city[root] != root: -            root = city[root] -        city[B] = root -    # 結合 -    if city[A] != city[B]: -        city[city[B]] = city[A] -# print(city) -# 木が何種類あるかチェック +    city.unite(A, B) -    if city[i] != i: -        root = city[i] -        while city[root] != root: -            root = city[root] -        city[i] = root -    if ck[city[i]] == 0: -        ck[city[i]] = 1 -# print(city) +    root = city.find(i) +    if ck[root] == 0: +        ck[root] = 1 +# print(city.par) -Ans = sum(ck) - 1  # 木の数-1=必要な道路数 +Ans = sum(ck) - 1