class UnionFind:

    def __init__(self, n):

        self.root = [i for i in range(n + 1)]

        self.rank = [0] * (n + 1)



    def find(self, x):

        if self.root[x] == x:

            return x

        else:

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

            return self.root[x]



    def isSame(self, x, y):

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



    def union(self, x, y):

        x = self.find(x)

        y = self.find(y)

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

            self.root[x] = y

        else:

            self.root[y] = x

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

                self.rank[x] += 1





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, y)



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

    uf.find(i)



n_tree = set(uf.root)

ans = len(n_tree) - 1

print(ans)

from collections import deque



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

graph = [[] * n for _ in range(n)]

for _ in range(m):

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

    x -= 1

    y -= 1

    z %= 2

    graph[x].append((y))

    graph[y].append((x))



seen = [False] * n

ans = 0

for i in range(n):

    if not seen[i]:

        seen[i] = True

        node = deque(graph[i])

        while node:

            v = node.popleft()

            if seen[v]:

                continue

            seen[v] = True

            node.extend(graph[v])

        ans += 1



print(ans)

class UnionFind:
    def __init__(self, n):
        self.root = [i for i in range(n + 1)]
        self.rank = [0] * (n + 1)

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

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

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            self.root[x] = y
        else:
            self.root[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1


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, y)
for i in range(1, n + 1):
    uf.find(i)
n_tree = set(uf.root)
ans = len(n_tree) - 1
print(ans)

from collections import deque

n, m = list(map(int, input().split()))
graph = [[] * n for _ in range(n)]
for _ in range(m):
    x, y, z = list(map(int, input().split()))
    x -= 1
    y -= 1
    z %= 2
    graph[x].append((y))
    graph[y].append((x))
seen = [False] * n
ans = 0
for i in range(n):
    if not seen[i]:
        seen[i] = True
        node = deque(graph[i])
        while node:
            v = node.popleft()
            if seen[v]:
                continue
            seen[v] = True
            node.extend(graph[v])
        ans += 1
print(ans)

-class UnionFind: -    def __init__(self, n): -        self.root = [i for i in range(n + 1)] -        self.rank = [0] * (n + 1) - -    def find(self, x): -        if self.root[x] == x: -            return x -        else: -            self.root[x] = self.find(self.root[x]) -            return self.root[x] - -    def isSame(self, x, y): -        return self.find(x) == self.find(y) - -    def union(self, x, y): -        x = self.find(x) -        y = self.find(y) -        if self.rank[x] < self.rank[y]: -            self.root[x] = y -        else: -            self.root[y] = x -            if self.rank[x] == self.rank[y]: -                self.rank[x] += 1 - +from collections import deque -uf = UnionFind(n) +graph = [[] * n for _ in range(n)] -    uf.union(x, y) -for i in range(1, n + 1): -    uf.find(i) -n_tree = set(uf.root) -ans = len(n_tree) - 1 +    x -= 1 +    y -= 1 +    z %= 2 +    graph[x].append((y)) +    graph[y].append((x)) +seen = [False] * n +ans = 0 +for i in range(n): +    if not seen[i]: +        seen[i] = True +        node = deque(graph[i]) +        while node: +            v = node.popleft() +            if seen[v]: +                continue +            seen[v] = True +            node.extend(graph[v]) +        ans += 1