# Union-Findデータ構造

class UnionFind:

    def __init__(self, numV):

        self.pars = list(range(numV))

        self.ranks = [0] * numV

    def find(self, x):

        if self.pars[x] == x: return x

        else:

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

            return self.pars[x]

    def union(self, x, y):

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

        if x == y: return

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

            self.pars[x] = y

        else:

            self.pars[y] = x

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

                self.ranks[x] += 1

    def same(self, x, y):

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





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



UF = UnionFind(N)

for _ in range(M):

    X, Y, Z = list(map(int, input().split()))

    UF.union(X-1, Y-1)



for i in range(N):

    UF.find(i)



parents = UF.pars

print((len(set(parents))))

class UnionFind:

    def __init__(self, numV):

        self.pars = list(range(numV))

        self.ranks = [0] * numV

    def getRoot(self, x):

        par = self.pars[x]

        if par != x:

            self.pars[x] = par = self.getRoot(par)

        return par

    def merge(self, x, y):

        x, y = self.getRoot(x), self.getRoot(y)

        if x == y: return

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

            self.pars[x] = y

        else:

            self.pars[y] = x

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

                self.ranks[x] += 1

    def isSame(self, x, y):

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

    def updatePars(self):

        for v in range(len(self.pars)):

            self.getRoot(v)



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



UF = UnionFind(N)

for _ in range(M):

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

    x, y = x-1, y-1

    UF.merge(x, y)



UF.updatePars()



ans = len(set(UF.pars))

print(ans)

# Union-Findデータ構造
class UnionFind:
    def __init__(self, numV):
        self.pars = list(range(numV))
        self.ranks = [0] * numV

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

    def union(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return
        if self.ranks[x] < self.ranks[y]:
            self.pars[x] = y
        else:
            self.pars[y] = x
            if self.ranks[x] == self.ranks[y]:
                self.ranks[x] += 1

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


N, M = list(map(int, input().split()))
UF = UnionFind(N)
for _ in range(M):
    X, Y, Z = list(map(int, input().split()))
    UF.union(X - 1, Y - 1)
for i in range(N):
    UF.find(i)
parents = UF.pars
print((len(set(parents))))

class UnionFind:
    def __init__(self, numV):
        self.pars = list(range(numV))
        self.ranks = [0] * numV

    def getRoot(self, x):
        par = self.pars[x]
        if par != x:
            self.pars[x] = par = self.getRoot(par)
        return par

    def merge(self, x, y):
        x, y = self.getRoot(x), self.getRoot(y)
        if x == y:
            return
        if self.ranks[x] < self.ranks[y]:
            self.pars[x] = y
        else:
            self.pars[y] = x
            if self.ranks[x] == self.ranks[y]:
                self.ranks[x] += 1

    def isSame(self, x, y):
        return self.getRoot(x) == self.getRoot(y)

    def updatePars(self):
        for v in range(len(self.pars)):
            self.getRoot(v)


N, M = list(map(int, input().split()))
UF = UnionFind(N)
for _ in range(M):
    x, y, z = list(map(int, input().split()))
    x, y = x - 1, y - 1
    UF.merge(x, y)
UF.updatePars()
ans = len(set(UF.pars))
print(ans)

-# Union-Findデータ構造 -    def find(self, x): -        if self.pars[x] == x: -            return x -        else: -            self.pars[x] = self.find(self.pars[x]) -            return self.pars[x] +    def getRoot(self, x): +        par = self.pars[x] +        if par != x: +            self.pars[x] = par = self.getRoot(par) +        return par -    def union(self, x, y): -        x, y = self.find(x), self.find(y) +    def merge(self, x, y): +        x, y = self.getRoot(x), self.getRoot(y) -    def same(self, x, y): -        return self.find(x) == self.find(y) +    def isSame(self, x, y): +        return self.getRoot(x) == self.getRoot(y) + +    def updatePars(self): +        for v in range(len(self.pars)): +            self.getRoot(v) -    X, Y, Z = list(map(int, input().split())) -    UF.union(X - 1, Y - 1) -for i in range(N): -    UF.find(i) -parents = UF.pars -print((len(set(parents)))) +    x, y, z = list(map(int, input().split())) +    x, y = x - 1, y - 1 +    UF.merge(x, y) +UF.updatePars() +ans = len(set(UF.pars)) +print(ans)