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

#union-find

par=[-1]*(n+1)

def find(x):

    if par[x]<0:

        return x

    else:

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

        return par[x]

def size(x):

    oya=find(x)

    return -par[oya]

def unite(x,y):

    if find(x)==find(y):

        return False

    else:

        if size(y)>size(x):

            y,x=x,y  #xを大きい親にしておくか

        oya_x=find(x)

        oya_y=find(y)

        par[oya_x]-=size(oya_y)  #xの大きさをyにしておく

        par[oya_y]=oya_x  #yの親をxに

        return True



def is_same(x,y):

    return find(x)==find(y)

for _ in range(m):

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

    unite(x,y)

ans_set=set()

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

    ans_set.add(find(i))

print((len(ans_set)))
import sys



input = sys.stdin.buffer.readline

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





# union-find

# xの根を求める





def find(x):

    if par[x] < 0:

        return x

    else:

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

        return par[x]





# xとyの属する集合の併合

def unite(x, y):

    x = find(x)

    y = find(y)

    if x == y:

        return False

    else:

        # sizeの大きい方をxとする

        if par[x] > par[y]:

            x, y = y, x

        par[x] += par[y]

        par[y] = x

        return True





# xとyが同じ集合か判定

def is_same(x, y):

    return find(x) == find(y)





def size(x):

    return -par[find(x)]





# 初期化

# 根なら-size、子なら親の頂点

par = [-1] * (n + 1)



for _ in range(m):

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

    unite(x, y)

ans = 0

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

    if i == find(i):

        ans += 1

print(ans)

n, m = list(map(int, input().split()))
# union-find
par = [-1] * (n + 1)


def find(x):
    if par[x] < 0:
        return x
    else:
        par[x] = find(par[x])
        return par[x]


def size(x):
    oya = find(x)
    return -par[oya]


def unite(x, y):
    if find(x) == find(y):
        return False
    else:
        if size(y) > size(x):
            y, x = x, y  # xを大きい親にしておくか
        oya_x = find(x)
        oya_y = find(y)
        par[oya_x] -= size(oya_y)  # xの大きさをyにしておく
        par[oya_y] = oya_x  # yの親をxに
        return True


def is_same(x, y):
    return find(x) == find(y)


for _ in range(m):
    x, y, z = list(map(int, input().split()))
    unite(x, y)
ans_set = set()
for i in range(1, n + 1):
    ans_set.add(find(i))
print((len(ans_set)))

import sys

input = sys.stdin.buffer.readline
n, m = list(map(int, input().split()))
# union-find
# xの根を求める
def find(x):
    if par[x] < 0:
        return x
    else:
        par[x] = find(par[x])
        return par[x]


# xとyの属する集合の併合
def unite(x, y):
    x = find(x)
    y = find(y)
    if x == y:
        return False
    else:
        # sizeの大きい方をxとする
        if par[x] > par[y]:
            x, y = y, x
        par[x] += par[y]
        par[y] = x
        return True


# xとyが同じ集合か判定
def is_same(x, y):
    return find(x) == find(y)


def size(x):
    return -par[find(x)]


# 初期化
# 根なら-size、子なら親の頂点
par = [-1] * (n + 1)
for _ in range(m):
    x, y, z = list(map(int, input().split()))
    unite(x, y)
ans = 0
for i in range(1, n + 1):
    if i == find(i):
        ans += 1
print(ans)

+import sys + +input = sys.stdin.buffer.readline -par = [-1] * (n + 1) - - +# xの根を求める -def size(x): -    oya = find(x) -    return -par[oya] - - +# xとyの属する集合の併合 -    if find(x) == find(y): +    x = find(x) +    y = find(y) +    if x == y: -        if size(y) > size(x): -            y, x = x, y  # xを大きい親にしておくか -        oya_x = find(x) -        oya_y = find(y) -        par[oya_x] -= size(oya_y)  # xの大きさをyにしておく -        par[oya_y] = oya_x  # yの親をxに +        # sizeの大きい方をxとする +        if par[x] > par[y]: +            x, y = y, x +        par[x] += par[y] +        par[y] = x +# xとyが同じ集合か判定 +def size(x): +    return -par[find(x)] + + +# 初期化 +# 根なら-size、子なら親の頂点 +par = [-1] * (n + 1) -ans_set = set() +ans = 0 -    ans_set.add(find(i)) -print((len(ans_set))) +    if i == find(i): +        ans += 1 +print(ans)