class UnionFind:

    def __init__(self, n):

        self.v = [-1 for _ in range(n)]  # 根(負): 連結頂点数 * (-1) / 子(正): 根の頂点番号(0-indexed)



    def find(self, x):  # xを含む木における根の頂点番号を返す

        if self.v[x] < 0:  # (負)は根

            return x

        else:  # 根の頂点番号

            self.v[x] = self.find(self.v[x])  # uniteでは, 旧根に属する頂点の根が旧根のままなので更新

            return self.v[x]



    def unite(self, x, y):  # 違う根に属していたらrankが低くなるように連結

        x = self.find(x)

        y = self.find(y)

        if x == y:

            return

        if -self.v[x] < -self.v[y]:  # size比較, 　(-1) * (連結頂点数 * (-1)), (正)同士の大小比較

            x, y = y, x  # 連結頂点数が少ない方をyにすると, findでの更新回数が減る？

        self.v[x] += self.v[y]  # 連結頂点数の和を取る, 連結頂点数 * (-1)

        self.v[y] = x  # 連結頂点数が少ないy(引数yの根の頂点番号)の根をx(引数xの根の頂点番号)にする



    def root(self, x):

        return self.v[x] < 0  # (負)は根



    def same(self, x, y):

        return self.find(x) == self.find(y)  # 同じ根に属するか



    def size(self, x):

        return -self.v[self.find(x)]  # 連結頂点数を返す





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



uf = UnionFind(N)

for _ in range(M):

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

    x -= 1

    y -= 1

    uf.unite(x, y)



ans = sum(1 for i in range(N) if uf.root(i))

print(ans)

class UnionFind():

    def __init__(self, n):

        self.parent = [-1 for _ in range(n)]

        # 正==子: 根の頂点番号 / 負==根: 連結頂点数



    def find(self, x):

        if self.parent[x] < 0:

            return x

        else:

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

            return self.parent[x]



    def unite(self, x, y):

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

        if x == y:

            return False

        else:

            if self.size(x) < self.size(y):

                x, y = y, x

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

            self.parent[y] = x



    def same(self, x, y):

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



    def size(self, x):

        x = self.find(x)

        return -self.parent[x]



    def is_root(self, x):

        return self.parent[x] < 0





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



uf = UnionFind(n)



for _ in range(m):

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

    x -= 1

    y -= 1

    uf.unite(x, y)



print((sum(uf.is_root(i) for i in range(n))))

class UnionFind:
    def __init__(self, n):
        self.v = [-1 for _ in range(n)]  # 根(負): 連結頂点数 * (-1) / 子(正): 根の頂点番号(0-indexed)

    def find(self, x):  # xを含む木における根の頂点番号を返す
        if self.v[x] < 0:  # (負)は根
            return x
        else:  # 根の頂点番号
            self.v[x] = self.find(self.v[x])  # uniteでは, 旧根に属する頂点の根が旧根のままなので更新
            return self.v[x]

    def unite(self, x, y):  # 違う根に属していたらrankが低くなるように連結
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if -self.v[x] < -self.v[y]:  # size比較, 　(-1) * (連結頂点数 * (-1)), (正)同士の大小比較
            x, y = y, x  # 連結頂点数が少ない方をyにすると, findでの更新回数が減る？
        self.v[x] += self.v[y]  # 連結頂点数の和を取る, 連結頂点数 * (-1)
        self.v[y] = x  # 連結頂点数が少ないy(引数yの根の頂点番号)の根をx(引数xの根の頂点番号)にする

    def root(self, x):
        return self.v[x] < 0  # (負)は根

    def same(self, x, y):
        return self.find(x) == self.find(y)  # 同じ根に属するか

    def size(self, x):
        return -self.v[self.find(x)]  # 連結頂点数を返す


N, M = list(map(int, input().split()))
uf = UnionFind(N)
for _ in range(M):
    x, y, z = list(map(int, input().split()))
    x -= 1
    y -= 1
    uf.unite(x, y)
ans = sum(1 for i in range(N) if uf.root(i))
print(ans)

class UnionFind:
    def __init__(self, n):
        self.parent = [-1 for _ in range(n)]
        # 正==子: 根の頂点番号 / 負==根: 連結頂点数

    def find(self, x):
        if self.parent[x] < 0:
            return x
        else:
            self.parent[x] = self.find(self.parent[x])
            return self.parent[x]

    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return False
        else:
            if self.size(x) < self.size(y):
                x, y = y, x
            self.parent[x] += self.parent[y]
            self.parent[y] = x

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

    def size(self, x):
        x = self.find(x)
        return -self.parent[x]

    def is_root(self, x):
        return self.parent[x] < 0


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

-        self.v = [-1 for _ in range(n)]  # 根(負): 連結頂点数 * (-1) / 子(正): 根の頂点番号(0-indexed) +        self.parent = [-1 for _ in range(n)] +        # 正==子: 根の頂点番号 / 負==根: 連結頂点数 -    def find(self, x):  # xを含む木における根の頂点番号を返す -        if self.v[x] < 0:  # (負)は根 +    def find(self, x): +        if self.parent[x] < 0: -        else:  # 根の頂点番号 -            self.v[x] = self.find(self.v[x])  # uniteでは, 旧根に属する頂点の根が旧根のままなので更新 -            return self.v[x] +        else: +            self.parent[x] = self.find(self.parent[x]) +            return self.parent[x] -    def unite(self, x, y):  # 違う根に属していたらrankが低くなるように連結 -        x = self.find(x) -        y = self.find(y) +    def unite(self, x, y): +        x, y = self.find(x), self.find(y) -            return -        if -self.v[x] < -self.v[y]:  # size比較, 　(-1) * (連結頂点数 * (-1)), (正)同士の大小比較 -            x, y = y, x  # 連結頂点数が少ない方をyにすると, findでの更新回数が減る？ -        self.v[x] += self.v[y]  # 連結頂点数の和を取る, 連結頂点数 * (-1) -        self.v[y] = x  # 連結頂点数が少ないy(引数yの根の頂点番号)の根をx(引数xの根の頂点番号)にする - -    def root(self, x): -        return self.v[x] < 0  # (負)は根 +            return False +        else: +            if self.size(x) < self.size(y): +                x, y = y, x +            self.parent[x] += self.parent[y] +            self.parent[y] = x -        return self.find(x) == self.find(y)  # 同じ根に属するか +        return self.find(x) == self.find(y) -        return -self.v[self.find(x)]  # 連結頂点数を返す +        x = self.find(x) +        return -self.parent[x] + +    def is_root(self, x): +        return self.parent[x] < 0 -N, M = list(map(int, input().split())) -uf = UnionFind(N) -for _ in range(M): +n, m = list(map(int, input().split())) +uf = UnionFind(n) +for _ in range(m): -ans = sum(1 for i in range(N) if uf.root(i)) -print(ans) +print((sum(uf.is_root(i) for i in range(n))))