class UnionFind():

    '''UnionFind木'''



    def __init__(self, n):

        self.data = [-1] * n



    def unite(self, x, y):

        '''x と y を結合'''

        x = self.find(x)

        y = self.find(y)

        if x == y:

            return

        elif self.data[x] < self.data[y]:

            x, y = y, x  # swap

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

        self.data[y] = x



    def find(self, x):

        '''ノード x の親を返す'''

        if self.data[x] < 0:

            return x

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

        return self.data[x]



    def same(self, x, y):

        '''x と y が同じグループに属するか判定'''

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



    def size(self, x):

        '''x を含むグループのノード数を返す'''

        return self.data[self.find(x)]

    def indep(self):

        dep = 0

        for i in range(len(self.data)):

            if self.data[i] < 0:

                dep += 1

        return dep





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

uf = UnionFind(n+1)

for i in range(m):

    x,y,z = list(map(int,input().split()))

    uf.unite(x,y)



print((uf.indep()-1))

class uf_tree():



    def __init__(self,n):

        self.n = n

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



    def indep(self):

        dep =0

        for i in range(self.n):

            if i == self.par[i]:

                dep += 1



        return dep



    def unite(self,child,mas):

        if self.root(child) == self.root(mas):

            return

        else:

            self.par[self.root(child)] = self.root(mas)



    def root(self,i):

        if self.par[i] == i:

            return i

        else:

            self.par[i] = self.root(self.par[i])

            return self.par[i]



    def same(self,x,y):

        if self.root(x) == self.root(y):

            return True

        else:

            return False







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

uf = uf_tree(n+1)

for i in range(m):

    x,y,z = list(map(int,input().split()))

    uf.unite(x,y)



print((uf.indep()-1))

class UnionFind:
    """UnionFind木"""

    def __init__(self, n):
        self.data = [-1] * n

    def unite(self, x, y):
        """x と y を結合"""
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        elif self.data[x] < self.data[y]:
            x, y = y, x  # swap
        self.data[x] += self.data[y]
        self.data[y] = x

    def find(self, x):
        """ノード x の親を返す"""
        if self.data[x] < 0:
            return x
        self.data[x] = self.find(self.data[x])
        return self.data[x]

    def same(self, x, y):
        """x と y が同じグループに属するか判定"""
        return self.find(x) == self.find(y)

    def size(self, x):
        """x を含むグループのノード数を返す"""
        return self.data[self.find(x)]

    def indep(self):
        dep = 0
        for i in range(len(self.data)):
            if self.data[i] < 0:
                dep += 1
        return dep


n, m = list(map(int, input().split()))
uf = UnionFind(n + 1)
for i in range(m):
    x, y, z = list(map(int, input().split()))
    uf.unite(x, y)
print((uf.indep() - 1))

class uf_tree:
    def __init__(self, n):
        self.n = n
        self.par = [i for i in range(n)]

    def indep(self):
        dep = 0
        for i in range(self.n):
            if i == self.par[i]:
                dep += 1
        return dep

    def unite(self, child, mas):
        if self.root(child) == self.root(mas):
            return
        else:
            self.par[self.root(child)] = self.root(mas)

    def root(self, i):
        if self.par[i] == i:
            return i
        else:
            self.par[i] = self.root(self.par[i])
            return self.par[i]

    def same(self, x, y):
        if self.root(x) == self.root(y):
            return True
        else:
            return False


n, m = list(map(int, input().split()))
uf = uf_tree(n + 1)
for i in range(m):
    x, y, z = list(map(int, input().split()))
    uf.unite(x, y)
print((uf.indep() - 1))

-class UnionFind: -    """UnionFind木""" - +class uf_tree: -        self.data = [-1] * n - -    def unite(self, x, y): -        """x と y を結合""" -        x = self.find(x) -        y = self.find(y) -        if x == y: -            return -        elif self.data[x] < self.data[y]: -            x, y = y, x  # swap -        self.data[x] += self.data[y] -        self.data[y] = x - -    def find(self, x): -        """ノード x の親を返す""" -        if self.data[x] < 0: -            return x -        self.data[x] = self.find(self.data[x]) -        return self.data[x] - -    def same(self, x, y): -        """x と y が同じグループに属するか判定""" -        return self.find(x) == self.find(y) - -    def size(self, x): -        """x を含むグループのノード数を返す""" -        return self.data[self.find(x)] +        self.n = n +        self.par = [i for i in range(n)] -        for i in range(len(self.data)): -            if self.data[i] < 0: +        for i in range(self.n): +            if i == self.par[i]: +    def unite(self, child, mas): +        if self.root(child) == self.root(mas): +            return +        else: +            self.par[self.root(child)] = self.root(mas) + +    def root(self, i): +        if self.par[i] == i: +            return i +        else: +            self.par[i] = self.root(self.par[i]) +            return self.par[i] + +    def same(self, x, y): +        if self.root(x) == self.root(y): +            return True +        else: +            return False + -uf = UnionFind(n + 1) +uf = uf_tree(n + 1)