class UnionFind:

    def __init__(self, n):

        self.r = [-1 for i in range(n)]

    

    def root(self, x):

        if self.r[x] < 0:

            return x

        self.r[x] = self.root(self.r[x])

        return self.r[x]

    

    def unite(self, x, y):

        x = self.root(x)

        y = self.root(y)

        if x == y:

            return False

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

            temp = x

            x = y

            y = temp

        self.r[x] += self.r[y]

        self.r[y] = x

        return True

    

    def size(self, x):

        return -self.r[self.root(x)]



n, m = list(map(int, input().split()))

UF = UnionFind(n)

for i in range(m):

    a, b = [int(x)-1 for x in input().split()]

    UF.unite(a, b)



ans = 0

for i in UF.r:

    if i < 0:

        ans += 1



print((ans-1))
#self.r[x] means root of "x" if "x" isn't root, else number of elements

class UnionFind():

    def __init__(self, n):

        self.r = [-1 for i in range(n)]

    

    #use in add-method

    def root(self, x):

        if self.r[x] < 0: #"x" is root

            return x

        self.r[x] = self.root(self.r[x])

        return self.r[x]



    #add new path

    def add(self, x, y):

        x = self.root(x)

        y = self.root(y)

        if x == y:

            return False

        self.r[x] += self.r[y]

        self.r[y] = x

        return True



n, m = list(map(int, input().split()))

UF = UnionFind(n)

for i in range(m):

    a, b = [int(x)-1 for x in input().split()]

    UF.add(a, b)



ans = 0

for i in UF.r:

    if i < 0:

        ans += 1



print((ans-1))

class UnionFind:
    def __init__(self, n):
        self.r = [-1 for i in range(n)]

    def root(self, x):
        if self.r[x] < 0:
            return x
        self.r[x] = self.root(self.r[x])
        return self.r[x]

    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.r[x] < self.r[y]:
            temp = x
            x = y
            y = temp
        self.r[x] += self.r[y]
        self.r[y] = x
        return True

    def size(self, x):
        return -self.r[self.root(x)]


n, m = list(map(int, input().split()))
UF = UnionFind(n)
for i in range(m):
    a, b = [int(x) - 1 for x in input().split()]
    UF.unite(a, b)
ans = 0
for i in UF.r:
    if i < 0:
        ans += 1
print((ans - 1))

# self.r[x] means root of "x" if "x" isn't root, else number of elements
class UnionFind:
    def __init__(self, n):
        self.r = [-1 for i in range(n)]

    # use in add-method
    def root(self, x):
        if self.r[x] < 0:  # "x" is root
            return x
        self.r[x] = self.root(self.r[x])
        return self.r[x]

    # add new path
    def add(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        self.r[x] += self.r[y]
        self.r[y] = x
        return True


n, m = list(map(int, input().split()))
UF = UnionFind(n)
for i in range(m):
    a, b = [int(x) - 1 for x in input().split()]
    UF.add(a, b)
ans = 0
for i in UF.r:
    if i < 0:
        ans += 1
print((ans - 1))

+# self.r[x] means root of "x" if "x" isn't root, else number of elements +    # use in add-method -        if self.r[x] < 0: +        if self.r[x] < 0:  # "x" is root -    def unite(self, x, y): +    # add new path +    def add(self, x, y): -        if self.r[x] < self.r[y]: -            temp = x -            x = y -            y = temp - -    def size(self, x): -        return -self.r[self.root(x)] -    UF.unite(a, b) +    UF.add(a, b)