Problem:
 Score : 500 points    Problem Statement There are N cards placed face down in a row. On each card, an integer 1 or 2 is written.  Let A_i be the integer written on the i -th card.  Your objective is to guess A_1, A_2, ..., A_N correctly.  You know the following facts:   For each i = 1, 2, ..., M , the value A_{X_i} + A_{Y_i} + Z_i is an even number.   You are a magician and can use the following magic any number of times:  Magic : Choose one card and know the integer A_i written on it. The cost of using this magic is 1 .  What is the minimum cost required to determine all of A_1, A_2, ..., A_N ?  It is guaranteed that there is no contradiction in given input.      Constraints  All values in input are integers.  2 \leq N \leq 10^5  1 \leq M \leq 10^5  1 \leq X_i < Y_i \leq N  1 \leq Z_i \leq 100  The pairs (X_i, Y_i) are distinct.  There is no contradiction in input. (That is, there exist integers A_1, A_2, ..., A_N that satisfy the conditions.)         Input Input is given from Standard Input in the following format:  N  M  X_1  Y_1  Z_1  X_2  Y_2  Z_2  \vdots  X_M  Y_M  Z_M       Output Print the minimum total cost required to determine all of A_1, A_2, ..., A_N .        Sample Input 1 3 1
1 2 1      Sample Output 1 2  You can determine all of A_1, A_2, A_3 by using the magic for the first and third cards.       Sample Input 2 6 5
1 2 1
2 3 2
1 3 3
4 5 4
5 6 5      Sample Output 2 2       Sample Input 3 100000 1
1 100000 100      Sample Output 3 99999

Solution (Python):
from collections import defaultdict

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

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

    def same_check(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]:
            if self.same_check(x, y) != True:
                self.size[y] += self.size[x]
                self.size[x] = 0
            self.par[x] = y
        else:
            if self.same_check(x, y) != True:
               self.size[x] += self.size[y]
               self.size[y] = 0
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
               self.rank[x] += 1

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

def getlist():
    return list(map(int, input().split()))

N, M = getlist()
U = UnionFind(N)
for i in range(M):
    X, Y, Z = getlist()
    U.union(X, Y)

D = defaultdict(int)


for i in range(1, N + 1):
    n = U.find(i)
    D[n] += 1

print(len(D))

Solution (Python):
from collections import defaultdict

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

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

    def same_check(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]:
            if self.same_check(x, y) != True:
                self.size[y] += self.size[x]
                self.size[x] = 0
            self.par[x] = y
        else:
            if self.same_check(x, y) != True:
               self.size[x] += self.size[y]
               self.size[y] = 0
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
               self.rank[x] += 1

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

def getlist():
    return list(map(int, input().split()))

N, M = getlist()
U = UnionFind(N)
for i in range(M):
    X, Y, Z = getlist()
    U.union(X, Y)

D = defaultdict(int)


for i in range(1, N + 1):
    n = U.find(i)
    D[n] += 1

print(len(D))

Solution (Python):
from bisect import bisect_left, bisect_right
from collections import Counter, defaultdict, deque, OrderedDict
from copy import deepcopy
from fractions import gcd
from functools import lru_cache, reduce
from math import ceil, floor
from sys import setrecursionlimit

import heapq as hq
import itertools as its
import operator as op



inf = float('inf')
N = 0


def set_inputs():
    global N
    return


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

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

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

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


def main():
    setrecursionlimit(100000)
    set_inputs()
    
    N, M = get_li()
    X, Y, Z = get_data(M, [int, int, int])
    uf = UnionFind(N)
    for x, y, _ in zip(X, Y, Z):
        uf.union(x, y)
    for i in range(N+1):
        uf.find(i)
    print(len(set(uf.par[1:])))
    return


def get_int():
    return int(input())


def get_float():
    return float(input())


def get_str():
    return input().strip()


def get_li():
    return [int(i) for i in input().split()]


def get_lf():
    return [float(f) for f in input().split()]


def get_lc():
    return list(input().strip())


def get_data(n, types, sep=None):
    if len(types) == 1:
        return [types[0](input().strip()) for _ in range(n)]
    return list(zip(*(
        [t(x) for t, x in zip(types, input().strip().split(sep=sep))]
        for _ in range(n)
    )))


if __name__ == '__main__':
    main()

Solution (Python):
from bisect import bisect_left, bisect_right
from collections import Counter, defaultdict, deque, OrderedDict
from copy import deepcopy
from fractions import gcd
from functools import lru_cache, reduce
from math import ceil, floor
from sys import setrecursionlimit

import heapq as hq
import itertools as its
import operator as op



inf = float('inf')
N = 0


def set_inputs():
    global N
    return


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

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

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

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


def main():
    setrecursionlimit(100000)
    set_inputs()
    
    N, M = get_li()
    X, Y, Z = get_data(M, [int, int, int])
    uf = UnionFind(N)
    for x, y, _ in zip(X, Y, Z):
        uf.union(x, y)
    for i in range(N+1):
        uf.find(i)
    print(len(set(uf.par[1:])))
    return


def get_int():
    return int(input())


def get_float():
    return float(input())


def get_str():
    return input().strip()


def get_li():
    return [int(i) for i in input().split()]


def get_lf():
    return [float(f) for f in input().split()]


def get_lc():
    return list(input().strip())


def get_data(n, types, sep=None):
    if len(types) == 1:
        return [types[0](input().strip()) for _ in range(n)]
    return list(zip(*(
        [t(x) for t, x in zip(types, input().strip().split(sep=sep))]
        for _ in range(n)
    )))


if __name__ == '__main__':
    main()

Solution (Python):
from collections import defaultdict

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

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

    def same_check(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]:
            if self.same_check(x, y) != True:
                self.size[y] += self.size[x]
                self.size[x] = 0
            self.par[x] = y
        else:
            if self.same_check(x, y) != True:
               self.size[x] += self.size[y]
               self.size[y] = 0
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
               self.rank[x] += 1

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

def getlist():
    return list(map(int, input().split()))

N, M = getlist()
U = UnionFind(N)
for i in range(M):
    X, Y, Z = getlist()
    U.union(X, Y)

D = defaultdict(int)


for i in range(1, N + 1):
    n = U.find(i)
    D[n] += 1

print(len(D))

Solution (Python):
from collections import defaultdict

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

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

    def same_check(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]:
            if self.same_check(x, y) != True:
                self.size[y] += self.size[x]
                self.size[x] = 0
            self.par[x] = y
        else:
            if self.same_check(x, y) != True:
               self.size[x] += self.size[y]
               self.size[y] = 0
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
               self.rank[x] += 1

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

def getlist():
    return list(map(int, input().split()))

N, M = getlist()
U = UnionFind(N)
for i in range(M):
    X, Y, Z = getlist()
    U.union(X, Y)

D = defaultdict(int)


for i in range(1, N + 1):
    n = U.find(i)
    D[n] += 1

print(len(D))

Solution (Python):
class UnionFind(object):
    def __init__(self, n=1):
        self.par = [i for i in range(n)]
        self.rank = [0 for _ in range(n)]

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

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

    def is_same(self, x, y):
        return self.find(x) == self.find(y)
    
n,m=map(int, input().split())
uf1=UnionFind(n)
for i in range(m):
    a,b,c=map(int, input().split())
    uf1.union(a-1,b-1)
for i in range(n):
    uf1.find(i)
print(len(set(uf1.par)))

Solution (Python):
from collections import defaultdict

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

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

    def same_check(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]:
            if self.same_check(x, y) != True:
                self.size[y] += self.size[x]
                self.size[x] = 0
            self.par[x] = y
        else:
            if self.same_check(x, y) != True:
               self.size[x] += self.size[y]
               self.size[y] = 0
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
               self.rank[x] += 1

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

def getlist():
    return list(map(int, input().split()))

N, M = getlist()
U = UnionFind(N)
for i in range(M):
    X, Y, Z = getlist()
    U.union(X, Y)

D = defaultdict(int)


for i in range(1, N + 1):
    n = U.find(i)
    D[n] += 1

print(len(D))

Solution (Python):
from collections import defaultdict

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

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

    def same_check(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]:
            if self.same_check(x, y) != True:
                self.size[y] += self.size[x]
                self.size[x] = 0
            self.par[x] = y
        else:
            if self.same_check(x, y) != True:
               self.size[x] += self.size[y]
               self.size[y] = 0
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
               self.rank[x] += 1

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

def getlist():
    return list(map(int, input().split()))

N, M = getlist()
U = UnionFind(N)
for i in range(M):
    X, Y, Z = getlist()
    U.union(X, Y)

D = defaultdict(int)


for i in range(1, N + 1):
    n = U.find(i)
    D[n] += 1

print(len(D))

Solution (Python):
class UnionFind:
    def __init__(self, size):
        self.data = [-1 for _ in range(size)]
    def find(self, x):
        if self.data[x] < 0:
            return x
        else:
            self.data[x] = self.find(self.data[x])
            return self.data[x]
    def union(self, x, y):
        x, y = self.find(x), self.find(y)
        if x != y:
            if self.data[y] < self.data[x]:
                x, y = y, x
            self.data[x] += self.data[y]
            self.data[y] = x
        return (x != y)
    def same(self, x, y):
        return (self.find(x) == self.find(y))
    def size(self, x):
        return -self.data[self.find(x)]


N, M = [int(i) for i in input().split()]

uf = UnionFind(N + 1)
for x, y, z in [[int(i) for i in input().split()] for _ in range(M)]:
    uf.union(x, y)

s = set()
for i in range(1, N + 1):
    s.add(uf.find(i))

print(len(s))

Solution (Python):
read = input
n, m = map(int, read().split())
f = [-1 for i in range(n + 1)] 
def find(x):
    if f[x]<0:
        return x
    else :
        f[x] = find(f[x])
        return f[x]
for i in range(m):
    x,y,z = map(int, read().split())
    if abs(x) < abs(y): 
        x,y = y,x
    fx = find(x)
    fy = find(y)
    if fx == fy:continue
    f[fx] = f[fx] - 1
    f[fy] = fx


ans = 0
for i in range(1, n+1): 
    if f[i] < 0:
        ans += 1
print(ans)

Solution (Python):
N, M = map(int, input().split(" "))
XYZ = [list(map(int, input().split(" "))) for _ in range(M)]

l = [[] for _ in range(N)]
for x, y, _ in XYZ:
    l[x-1].append(y-1)
    l[y-1].append(x-1)

visited = [False]*N
count = 0
for i in range(N):
    
    if visited[i] == True:
        continue
    visited[i] = True
    q = l[i]
    while q:
        r = []
        for y in q:
            if visited[y] == True:
                continue
            visited[y] = True
            r += l[y]
        q = r
        
    count += 1
    


print(count)

Solution (Python):
inpl = lambda: list(map(int,input().split()))
import numpy as np
class ParityTree:
    def __init__(self,N):
        self.parent = [-1]*int(N)
        self.parity = [0]*int(N)

    def root(self, n):
        if self.parent[n] < 0:
            return n, 0
        else:
            m, p = self.root(self.parent[n])
            self.parent[n] = m
            self.parity[n] = (p + self.parity[n]) % 2
            return m, self.parity[n]

    def merge(self, m, n, parity):
        rm, pm = self.root(m)
        rn, pn = self.root(n)
        if rm != rn:
            if -self.parent[rm] < -self.parent[rn]:
                rm, rn = rn, rm
            self.parent[rm] += self.parent[rn]
            self.parent[rn] = rm
            self.parity[rn] = (pm + pn + parity) % 2

    def size(self, n):
        return -self.parent[self.root(n)]
    
    def aresame(self, m, n):
        return self.root(m) == self.root(n)

N, M = inpl()
pt = ParityTree(N)
for i in range(M):
    X, Y, Z = inpl()
    pt.merge(X-1,Y-1,Z)

print(len(np.where(np.array(pt.parent)<0)[0]))

Solution (Python):
import sys
sys.setrecursionlimit(10**6)



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

root = list(range(N+1))
depth = [0] * (N+1)

def find_root(x):
  y = root[x]
  if x == y:
    return x
  z = find_root(y)
  root[x] = z
  return z

def merge(x,y):
  global n_component
  xx = find_root(x)
  yy = find_root(y)
  if xx == yy:
    return
  n_component -= 1
  if depth[xx] >= depth[yy]:
    root[yy] = xx
    depth[xx] += 1
  else:
    root[xx] = yy
    depth[yy] += 1
  
for _ in range(M):
  x,y,z = [int(x) for x in input().split()]
  merge(x,y)

answer = n_component
print(answer)

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

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

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

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


n, m = map(int, raw_input().split(" "))
uf = UnionFind(n)

for i in range(0, m):
    x, y, z = map(int, raw_input().split(" "))
    uf.union(x - 1, y - 1)

counter = set()
for i in range(0, n):
    a = uf.find(i)
    
    counter.add(uf.find(i))

print(len(counter))

Solution (Python):
class uf_tree:
    def __init__(self, n):
        self._size = n
        self.sizes = [1] * n
        self.par = list(range(n))
 
    def find(self, x):
        if x == self.par[x]:
            return x
        self.par[x] = self.find(self.par[x])
        return self.par[x]
 
    def unite(self, x, y):
        self._size -= 1
        x, y = self.find(x), self.find(y)
        if x == y:
            return
        if self.sizes[x] < self.sizes[y]:
            x, y = y, x
        self.par[y] = x
        self.sizes[x] += self.sizes[y]
 
    def same(self, x, y):
        return self.find(x) == self.find(y)
 
    def size(self, x):
        return self.sizes[self.find(x)]


n, m = map(int, input().split())
uf = uf_tree(n+1)

for _ in range(m):
    x, y, z = map(int, input().split())
    if uf.same(x, y):
        continue
    uf.unite(x, y)

print(uf._size - 1)

Solution (Python):
class UnionFind():
    
    
    def __init__(self, n):
        self.n = n
        
        
        self.root = [-1]*(n+1)
        
        self.rnk = [0]*(n+1)

    
    def Find_Root(self, x):
        if(self.root[x] < 0):
            return x
        else:
            
            self.root[x] = self.Find_Root(self.root[x])
            return self.root[x]
    
    def Unite(self, x, y):
        
        x = self.Find_Root(x)
        y = self.Find_Root(y)
        
        if(x == y):
            return 
        
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1
    
    def isSameGroup(self, x, y):
        return self.Find_Root(x) == self.Find_Root(y)

    
    def Count(self, x):
        return -self.root[self.Find_Root(x)]



if __name__ == "__main__":

    

    N, M = map(int,input().split())
    uf = UnionFind(N+1)
    for i in range(M):
        X,Y,Z = map(int,input().split())
        if not uf.isSameGroup(X,Y):
            uf.Unite(X,Y)
    print(sum([1 for i in uf.root[1:N+1] if i <0]))

Solution (Python):
n, m = map(int, input().split())
p1 = [i for i in range(n)]
s1 = [1 for _ in range(n)]

def root(i):
  if p1[i] == i:
    return i
  else:
    p1[i] = root(p1[i])
    return p1[i]

def unite(i, j):
  pi = root(i)
  pj = root(j)
  if pi == pj:
    return
  else:
    if s1[pi] < s1[pj]:
      p1[pi] = pj
    elif s1[pj] < s1[pi]:
      p1[pj] = pi
    else:
      if pi < pj:
        p1[pj] = pi
        s1[pi] += 1
      else:
        p1[pi] = pj
        s1[pj] += 1

for _ in range(m):
  x, y, z = map(int, input().split())
  unite(x-1, y-1)

for i in range(n):
  root(i)

print(len(set(p1)))

Solution (Python):
import sys
sys.setrecursionlimit(2000000)
def func(c,x):
    c[x][0] = 1
    for i in c[x][1:]:
        if c[i][0] == 0:
            func(c,i)
    return c


N,M = map(int,input().split())
XYZ = list(list(map(int,input().split()))for i in range(M))

card = [[0]for i in range(N)]
set = 0


for x,y,z in XYZ:
    card[x-1].append(y-1)
    card[y-1].append(x-1)

for i in range(N):
    if card[i][0] == 0:
        set += 1
        card = func(card,i)

print(set)

Solution (Python):
class Unionfind():
    def __init__(self, size):
        self.table = [-1 for _ in range(size)]

    def find(self, x):
        while(self.table[x] >= 0):
            x = self.table[x]
        return x

    def union(self, x, y):
        xp = self.find(x)
        yp = self.find(y)
        if xp != yp:
            if self.table[xp] <= self.table[yp]:
                self.table[xp] += self.table[yp]
                self.table[yp] = xp
            else:
                self.table[yp] += self.table[xp]
                self.table[xp] = yp

n, m = map(int, input().split())
clue = Unionfind(n)
for _ in range(m):
    x, y, _ = map(int, input().split())
    clue.union(x-1, y-1)
roots = set()
for i in range(n):
    roots.add(clue.find(i))
print(len(roots))

Solution (Python):
from collections import defaultdict


class UnionFindTree:
    def __init__(self):
        self.p = {}
        self.rank = {}

    def make(self, x):
        self.p[x] = x
        self.rank[x] = 0

    def find(self, x):
        if x in self.p:
            if self.p[x] != x:
                
                self.p[x] = self.find(self.p[x])
            return self.p[x]
        return None

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

    def unite(self, x, y):
        return self._unite(self.find(x), self.find(y))

    def _unite(self, x, y):
        if self.rank[x] < self.rank[y]:
            self.p[x] = y
            return y
        else:
            self.p[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            return x


utf = UnionFindTree()

N, M = map(int, input().split())
for n in range(N):
    utf.make(n + 1)

for m in range(M):
    x, y, z = map(int, input().split())
    utf.unite(x, y)

h = defaultdict(int)
for n in range(N):
    x = utf.find(n + 1)
    h[x] += 1

ans = 0
rest = N
for k, v in h.items():
    ans += 1
    rest -= v
print(ans + rest)

Solution (Python):
import sys
sys.setrecursionlimit(100000)
N, M = [int(_) for _ in input().split()]
XYZ = [[int(_) for _ in input().split()] for _ in range(M)]

UF = list(range(N + 1))


def find(x):
    if UF[x] != x:
        UF[x] = find(UF[x])
    return UF[x]


def unite(x, y):
    UF[find(x)] = find(y)


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


for x, y, z in XYZ:
    unite(x, y)
s = set()
for i in range(1, N + 1):
    s.add(find(i))
print(len(set(s)))

Solution (Python):
if __name__ == '__main__':
    import sys
    input = sys.stdin.readline

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

    parent = {x:[] for x in range(1,n+1)}

    na_num = 1

    for _ in range(m):
        u,v,w = map(int, input().split())
        parent[u].append(v)
        parent[v].append(u)

    base = [1]

    ans = 0

    for i in range(2,n+1):
        if len(parent[i]) == 0:
            ans += 1

    while True:
        pop_num = base.pop()
        for i in parent[pop_num]:
            parent[i].remove(pop_num)
            base.append(i)
        parent[pop_num] = []
        if len(base) == 0:
            ans += 1
            while len(parent[na_num]) == 0:
                na_num += 1
                if na_num == n+1:
                    print(ans)
                    exit()
            base.append(na_num)

Solution (Python):


import sys

sys.setrecursionlimit(1000000)

N, M = [int(x) for x in input().split()]


D = [[] for i in range(N)]
for i in range(M):
    x, y, z = [int(x) for x in input().split()]
    x -= 1
    y -= 1
    D[x].append(y)
    D[y].append(x)

visited = [False for i in range(N)]
def dfs(n):
    for idx in D[n]:
        if not visited[idx]:
            visited[idx] = True
            dfs(idx)

cnt = 0
for n in range(N):
    if not visited[n]:
        visited[n] = True
        dfs(n)
        cnt += 1
print(cnt)

Solution (Python):

from collections import defaultdict


def get_dic(dic_data, x):
    while x != dic_data[x]:
        x = dic_data[x]
    return x

def main():
    num, hinto = map(int, input().split())
    data_flg = [-1 for i in range(num + 1)]
    ans = 0
    modoru = 0

    dic_data = {i: i for i in range(num + 1)}

    real_ans = 0

    for i in range(hinto):
        x, y, z = map(int, input().split())

        if data_flg[x] == -1 and data_flg[y] == -1:
            data_flg[x] = ans
            data_flg[y] = ans
            ans += 1
            real_ans += 1
        elif data_flg[x] == -1 or data_flg[y] == -1:
            aaa = max(data_flg[x], data_flg[y])
            data_flg[x] = aaa
            data_flg[y] = aaa
        else:
            
            nnn = get_dic(dic_data, data_flg[x])
            bbb = get_dic(dic_data, data_flg[y])
            if nnn != bbb:
                dic_data[nnn] = ans
                dic_data[bbb] = ans
                modoru += 1
                ans += 1

    real_ans -= modoru

    for i in range(1, num + 1):
        if data_flg[i] == -1:
            real_ans += 1

    print(real_ans)




if __name__ == '__main__':
    main()

Solution (Python):
from math import *



class V:
    def __init__(self,si):
        self.si = si
        self.parent = self
    def isInnovator(self):
        return self.parent == self
    def findInnovator(self):
        re = self
        while True:
            if re.parent == re:
                self.parent = re
                return re
            re = re.parent


N,K = tuple(map(int,input().split()))
vs = [V(vi) for vi in range(N)]

for _ in range(K):
    ui,vi,w = tuple(map(int,input().split()))
    ui-=1
    vi-=1
    u = vs[ui]
    v = vs[vi]
    uInnov = u.findInnovator()
    vInnov = v.findInnovator()
    if uInnov == vInnov:
        continue
    vInnov.parent = uInnov

re = 0
for v in vs:
    if v.isInnovator():
        re += 1

print(re)

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

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

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

    
    def size(self, x):
        return self.count[self.par[x]]

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

n,m=map(int,input().split())
UF=UnionFind(n)
for i in range(m):
    x,y,z=map(int,input().split())
    UF.union(x,y)
cnt=0
S=set()
for i in range(1,n+1):
    x=UF.find(i)
    if x not in S:
        cnt+=1
        S.add(x)
print(cnt)

Solution (Python):

"""
Created on Sun May 19 22:22:33 2019

@author: Yamazaki Kenichi
"""

N,M = map(int,input().split())
xyz = [list(map(int,input().split())) for i in range(M)]

import sys
sys.setrecursionlimit(10**6)

class UnionFind(object):

    def __init__(self, size):
        self.table = [-1 for _ in range(size)]

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

    def union(self, x, y):
        s1 = self.find(x)
        s2 = self.find(y)
        if s1 != s2:
            if self.table[s1] <= self.table[s2]:
                self.table[s1] += self.table[s2]
                self.table[s2] = s1
            else:
                self.table[s2] += self.table[s1]
                self.table[s1] = s2
            return True
        else:
            return False

uf = UnionFind(N+1)
for c in xyz:
    uf.union(c[0],c[1])
ans = -1
for u in uf.table:
    if u<0:
        ans += 1
print(ans)

Solution (Python):
N, M = map(int, input().split())
graph = [[] for i in range(N)]
for i in range(M):
    x, y, z = map(int, input().split())
    x, y = x-1, y-1
    graph[x].append(y)
    graph[y].append(x)
visited = [False for i in range(N)]
def bfs(v):
    Q = []
    visited[v] = True
    Q.append(v)
    while len(Q) > 0:
        v = Q.pop(0)
        for u in graph[v]:
            if not visited[u]:
                visited[u] = True
                Q.append(u)

count = 0
for i in range(N):
    if not visited[i]:
        bfs(i)
        count += 1
print(count)

Solution (Python):

import bisect
import heapq
import math
import random
import sys
from collections import Counter, defaultdict, deque
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations
from operator import add, mul, sub

sys.setrecursionlimit(100000)


def read_int():
    return int(input())


def read_int_n():
    return list(map(int, input().split()))


def read_float():
    return float(input())


def read_float_n():
    return list(map(float, input().split()))


def read_str():
    return input().strip()


def read_str_n():
    return list(map(str, input().split()))


def error_print(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.time()
        ret = f(*args, **kwargs)
        e = time.time()

        error_print(e - s, 'sec')
        return ret

    return wrap


@mt
def slv(N, M, XYZ):
    g = defaultdict(dict)
    for x, y, z in XYZ:
        g[x][y] = z % 2
        g[y][x] = z % 2

    ans = 0
    done = set()
    for i in range(1, N+1):
        if i in done:
            continue
        ans += 1
        q = deque([i])
        while q:
            u = q.popleft()
            done.add(u)
            for v in g[u]:
                if v not in done:
                    q.append(v)
                    done.add(v)
    return ans


def main():
    
    N, M = read_int_n()
    XYZ = [read_int_n() for _ in range(M)]
    print(slv(N, M, XYZ))

    
    


if __name__ == '__main__':
    main()