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):
class UnionFind():
    def __init__(self, N):
        self.par = [i for i in range(N)]
        self.rank = [0 for _ in range(N)]
        self.size = [1 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]:
                self.rank[x] += 1
            elif self.rank[x] < self.rank[y]:
                x, y = y, x
            self.par[y] = x
            self.size[x] += self.size[y]

    def is_same(self, x, y):
        return self.find(x) == self.find(y)
    
    def get_size(self, x):
        x = self.find(x)
        return self.size[x]

n, m = map(int, input().split())
uf = UnionFind(n)
for i in range(m):
    x, y, z = map(int, input().split())
    x, y = x-1, y-1
    uf.union(x, y)

s = set()
for i in range(n):
    parent = uf.find(i)
    s.add(parent)
print(len(s))

Solution (Python):
import numpy as np
from scipy.sparse import csr_matrix
from scipy.sparse.csgraph import connected_components

N, M = map(int, input().split())
edge = np.array([input().split() for _ in range(M)], dtype=np.int64).T

matr = csr_matrix(([1 for _ in range(M)], (edge[:2] - 1)), (N, N))
print(connected_components(matr, return_labels=False))

Solution (Python):
from operator import itemgetter
from collections import deque
n,m=map(int,input().split())
d=dict()
edge=[[] for i in range(n)]
for i in range(m):
  x,y,z=map(int,input().split())
  edge[x-1].append(y-1)
  edge[y-1].append(x-1)
  if x-1 not in d:
    d[x-1]=1
  else:
    d[x-1]+=1
  if y-1 not in d:
    d[y-1]=1
  else:
    d[y-1]+=1
d=sorted(list(d.items()),key=itemgetter(1),reverse=True)
visited=[0]*n
def bfs(edge,visited,s):
  q=deque([s])
  visited[s]=1
  while q:
    x=q.popleft()
    for i in edge[x]:
      newx=i
      if newx<n:
        if visited[newx]!=1:
          visited[newx]=1
          q.append(newx)
  return visited
ans=0
for i in range(len(d)):
  if visited[d[i][0]]==0:
    visited=bfs(edge,visited,d[i][0])
    ans+=1
print(ans+n-sum(visited))

Solution (Python):
import sys
input = sys.stdin.buffer.readline
sys.setrecursionlimit(10**5)

def main():
    N,M = map(int,input().split())
    use = [False for _ in range(N)]
    formula = 0
    
    I = [i for i in range(N)]
    rank = [1 for _ in range(N)]
    def root(x):
        if x == I[x]:
            return x
        I[x] = root(I[x])
        return I[x]
    
    def unite(x,y):
        px,py = root(x),root(y)
        rx,ry = rank[px],rank[py]
        if rx > ry:
            I[py] = px
        else:
            I[px] = py
            if rx == ry:
                rank[py] += 1

    for i in range(M):
        x,y,z = map(int,input().split())
        x -= 1
        y -= 1
        px,py = root(x),root(y)
        if px == py:
            continue
        else:
            unite(x,y)
            formula += 1

    print(N-formula)

if __name__ == "__main__":
    main()

Solution (Python):
import sys
input = sys.stdin.buffer.readline
sys.setrecursionlimit(10**5)

def main():
    N,M = map(int,input().split())
    use = [False for _ in range(N)]
    formula = 0
    
    I = [i for i in range(N)]
    rank = [1 for _ in range(N)]
    def root(x):
        if x == I[x]:
            return x
        I[x] = root(I[x])
        return I[x]
    
    def unite(x,y):
        px,py = root(x),root(y)
        if x < y:
            I[py] = px
        else:
            I[px] = py

    for i in range(M):
        x,y,z = map(int,input().split())
        x -= 1
        y -= 1
        px,py = root(x),root(y)
        if px == py:
            continue
        else:
            unite(x,y)
            formula += 1

    print(N-formula)

if __name__ == "__main__":
    main()

Solution (Python):
import sys
sys.setrecursionlimit(1000000)

n, m = map(int, input().split())
edge = {i: [] for i in range(1, n+1)}
graph = {i: -1 for i in range(1, n+1)}

for _ in range(m):
  x, y, z = list(map(int, input().split()))
  edge[x].append(y)
  edge[y].append(x)

def color_graph(i, v):
  if graph[i] == -1:
    graph[i] = v
    for j in edge[i]:
      color_graph(j, v)

ans = 0
for i in range(1, n+1):
  if graph[i] == -1:
    ans += 1
    color_graph(i, i)


print(ans)

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1]*n  

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

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

        if self.parents[x] > self.parents[y]:  
            
            x, y = y, x  

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

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

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

    def members(self, x):  
        root = self.find(x)  
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_counts(self):
        return len(self.roots())  

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}  

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())


N, M = map(int, input().split())
uf = UnionFind(N)
for _ in range(M):
    x, y, z = map(int, input().split())
    x -= 1
    y -= 1
    uf.union(x, y)

print(uf.group_counts())

Solution (Python):

import sys
sys.setrecursionlimit(10000000)
INF = 1<<32

class UnionFind:
    def __init__(self, n):
        
        self.par = [-1] * (n+1)
        
        self.rank = [0] * (n+1)
    
    
    def size(self, x):
        return -1*self.par[self.find(x)]
    
    def size_list(self):
        return [x*(-1) for x in self.par[1:] if x < 0]

    
    def find(self, x):
        
        if(self.par[x] < 1):
            return x
        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(x == y):
            return False

        
        if(self.size(x) < self.size(y)):
            x,y = y,x
        
        
        self.par[x] += self.par[y]
        
        self.par[y] = x

        return True 

    def root_nodes(self):
        
        return len([i for i in self.par[1:] if i <= -1])


def solve(N: int, M: int, X: "List[int]", Y: "List[int]", Z: "List[int]"):
    uf = UnionFind(N)
    for i in range(M):
        uf.union(X[i], Y[i])
    print(uf.root_nodes())
    return



def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  
    M = int(next(tokens))  
    X = [int()] * (M)  
    Y = [int()] * (M)  
    Z = [int()] * (M)  
    for i in range(M):
        X[i] = int(next(tokens))
        Y[i] = int(next(tokens))
        Z[i] = int(next(tokens))
    solve(N, M, X, Y, Z)

if __name__ == '__main__':
    main()

Solution (Python):
N,M = map(int,input().split())
xy = [[] for i in range(N)]
alr = [1 for i in range(N)]
for i in range(M):
    x,y,z = map(int,input().split())
    xy[x-1].append(y-1)
    xy[y-1].append(x-1)
    alr[x-1] = 0
    alr[y-1] = 0
count = sum(alr)
stack = []
for i in range(N):
    if not alr[i]:
        stack.append(xy[i])
        alr[i] = 1
        if xy[i]:
            count += 1
        while stack:
            now = stack.pop()
            for j in now:
                if not alr[j]:
                    alr[j] = 1
                    stack.append(xy[j])
print(count)

Solution (Python):
from _collections import deque
from _ast import Num


def parser():
    while 1:
        data = list(input().split(' '))
        for number in data:
            if len(number) > 0:
                yield (number)


input_parser = parser()


def gw():
    global input_parser
    return next(input_parser)


def gi():
    data = gw()
    return int(data)


MOD = int(1e9 + 7)

import numpy
from collections import deque
from math import sqrt
from math import floor
import heapq


"""
"""
N = gi()
M = gi()
parent = [[] for i in range(N + 1)]


def find(a):
    if parent[a] != a:
        parent[a] = find(parent[a])

    return parent[a]


def union(a, b):
    aP = find(a)
    bP = find(b)

    if (aP != bP):
        parent[max(aP, bP)] = min(aP, bP)


for i in range(N + 1):
    parent[i] = i

for i in range(M):
    x = gi()
    y = gi()
    z = gi()
    union(x, y)

ans = 0

for i in range(1, N + 1):
    if find(i) == i:
        ans += 1

print(ans)

Solution (Python):
import sys
sys.setrecursionlimit(10000000)

def visit_tree(now, num):
    visited[now] = num
    for i in range(len(tree[now])):
        if not visited[tree[now][i]]:
            visit_tree(tree[now][i], num)

n, m = map(int, input().split())
tree = [[] for _ in range(n)]
for i in range(m):
    x, y, z = map(int, input().split())
    tree[x - 1].append(y - 1)
    tree[y - 1].append(x - 1)

visited = [0 for _ in range(n)]
num = 0
for i in range(n):
    if not visited[i]:
        num += 1
        visit_tree(i, num)

print(num)

Solution (Python):
N,M=map(int, input().split())
E=[[] for _ in range(N)]
for _ in range(M):
    x,y,z=map(lambda i:int(i)-1, input().split())
    E[x].append(y)
    E[y].append(x)



G=[0]*(N+1)

def dfs(root,g):
    stack=[root]
    G[root]=g
    while stack:
        node=stack.pop()
        for to in E[node]:
            if G[to]==0:
                G[to]=g
                stack.append(to)

ans=0
for i in range(N):
    if G[i]==0:
        ans+=1
        dfs(i,ans)

print(ans)

Solution (Python):
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**9)


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

GRAPH = {i:[] for i in range(1, n + 1)}
for _ in range(m):
    x, y, z = map(int, input().split())
    GRAPH[x].append(y)
    GRAPH[y].append(x)

def dfs(now):
    SEARCHED[now] = True
    for v in GRAPH[now]:
        if SEARCHED[v]:
            continue
        next = v
        dfs(next)

SEARCHED = {i:False for i in range(1, n + 1)}
count = 0
for i in range(1, n + 1):
    if SEARCHED[i]:
        continue
    dfs(i)
    count += 1

print(count)

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

e_list = [[] for i in range(N)]

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

count = 0

color_list = [-1]*N

from collections import deque

def BFS(vi,c):
    Q = deque([vi])
    while len(Q)>0:
        v = Q.pop()
        for v1 in e_list[v]:
            if color_list[v1]==-1:
                color_list[v1]=c
                Q.appendleft(v1)

for i in range(N):
    if color_list[i]==-1:
        BFS(i,count)
        count+=1

print(count)

Solution (Python):
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

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

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

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

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

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

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())
      
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)
  
print(uf.group_count())

Solution (Python):
import sys
sys.setrecursionlimit(10 ** 6)
def dfs(v):
    global gone
    stack = [v]
    gone[v] = True
    while stack:
        v = stack.pop()
        for w in graph[v]:
            if gone[w] == False:
                stack.append(w)
            gone[w] = True

n,m = map(int,input().split())
exist = [False for i in range(n+1)]
gone = [False for i in range(n+1)]
graph = [[] for _ in range(n+1)]
for i in range(m):
    x,y,z = map(int,input().split())
    graph[x].append(y)
    graph[y].append(x)
    exist[x] = True
    exist[y] = True
ans = 0

for i in range(1,n+1):
    if exist[i] == True:
        if gone[i] == False:
            dfs(i)
            ans += 1
    else:
        ans += 1

print(ans)

Solution (Python):

n, m = list(map(int, input().split()))
edges = [[] for i in range(n)]
for i in range(m):
    tx, ty, _tz = list(map(int, input().split()))
    edges[tx-1].append(ty-1) 
    edges[ty-1].append(tx-1) 
visited = [False] * n
ans = 0
for i in range(n):
    if not visited[i]:
        q = [i]
        visited[i] = True
        while q:
            u = q.pop(0)
            for v in edges[u]:
                if not visited[v]:
                    q.append(v)
                    visited[v] = True
        ans += 1
print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n
        self.size = n

    def find(self, id):
        if id != self.parent[id]:
            self.parent[id] = self.find(self.parent[id])
        return self.parent[id]

    def union(self, id1, id2):
        par1, par2 = self.find(id1), self.find(id2)
        if par1 == par2:
            return
        if self.rank[par1] > self.rank[par2]:
            self.parent[par2] = par1
        else:
            self.parent[par1] = par2
            if self.rank[par1] == self.rank[par2]:
                self.rank[par2] += 1
        self.size -= 1

nVertices, nEdges = map(int, input().split())
unionFind = UnionFind(nVertices)
for _ in range(nEdges):
    u, v, _ = map(lambda x: int(x) - 1, input().split())
    unionFind.union(u, v)
print(unionFind.size)

Solution (Python):
from sys import setrecursionlimit
setrecursionlimit(100000)
from collections import deque

nVertices, nEdges = map(int, input().split())
g = [[] for _ in range(nVertices + 1)]
for _ in range(nEdges):
    u, v, _ = map(int, input().split())
    g[u].append(v)
    g[v].append(u)

def dfs(v):
    visited[v] = True
    for to in g[v]:
        if not visited[to]:
            dfs(to)

def bfs(v):
    visited[v] = True
    q = deque([v])
    while q:
        cur = q.pop()
        for to in g[cur]:
            if not visited[to]:
                visited[to] = True
                q.appendleft(to)

cnt = 0
visited = [False] * (nVertices + 1)
for v in range(1, nVertices + 1):
    if not visited[v]:
        bfs(v)
        cnt += 1
print(cnt)

Solution (Python):
n, m = map(int, input().split())
edges = [[] for i in range(n)]
for i in range(m):
    x, y, z = map(int, input().split())
    edges[x - 1].append(y - 1)
    edges[y - 1].append(x - 1)
visited = [False] * n
ret = 0
for i in range(n):
    if not visited[i]:
        q = [i]
        visited[i] = True
        while len(q) > 0:
            u = q.pop(0)
            for v in edges[u]:
                if not visited[v]:
                    q.append(v)
                    visited[v] = True
        ret += 1
print(ret)

Solution (Python):

import re
import math
import fractions
import random
import time

mod=int(10**9+7)
inf=int(10**20)

class union_find():
    def __init__(self,n):
        self.n=n
        self.P=[a for a in range(N)]
        self.rank=[0]*n

    def find(self,x):
        if(x!=self.P[x]):self.P[x]=self.find(self.P[x])
        return self.P[x]

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

    def link(self,x,y):
        if self.rank[x]<self.rank[y]:
            self.P[x]=y
        elif self.rank[y]<self.rank[x]:
            self.P[y]=x
        else:
            self.P[x]=y
            self.rank[y]+=1

    def unite(self,x,y):
        self.link(self.find(x),self.find(y))

    def size(self):
        S=set()
        for a in range(self.n):
            S.add(self.find(a))
        return len(S)




def solve():
    return


N,M=map(int,input().split())
XYZ=[]

U=union_find(N)
for a in range(M):
    X,Y,Z=map(int,input().split())
    X-=1
    Y-=1
    U.unite(X,Y)
print(U.size())

Solution (Python):

from collections import defaultdict
import heapq

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

es = [[] for _ in range(N)]
counts = defaultdict(int)
for i in range(M):
    x,y,z = map(int, input().split())
    es[x-1].append(y-1)
    es[y-1].append(x-1)
    counts[x-1] += 1
    counts[y-1] += 1


q = []

for k in counts.keys():
    heapq.heappush(q, (-counts[k], k))

visited = [False] * N
stack = []
cnt = 0
while q:
    _, curr = heapq.heappop(q)
    if visited[curr]:
        continue
    cnt += 1
    stack.append(curr)
    while stack:
        ns = stack.pop()
        if visited[ns]:
            continue
        visited[ns] = True
        for nns in es[ns]:
            if not visited[nns]:
                stack.append(nns)

print(visited.count(False) + cnt)

Solution (Python):

from bisect import *
from collections import *
from heapq import *



N,M=map(int,input().split())
XYZ=[list(map(int,input().split())) for i in range(M)]
data=[[] for i in range(N+1)]
ittenai=[]
for x,y,z in XYZ:
    data[x].append(y)
    data[y].append(x)
    ittenai.append(x)
    ittenai.append(y)


ittenai=set(ittenai)
count=N-len(ittenai)
while ittenai:
    x=ittenai.pop()
    stack=deque([x])

    count+=1
    while stack:
        num=stack.popleft()
        for i in data[num]:
            if i in ittenai:
                ittenai.remove(i)
                stack.append(i)
print(count)

Solution (Python):
import sys
input = sys.stdin.readline


class UnionFind():
    """
    parents : 親要素(findしない場合は根ではないことの注意)，根の場合は"-(要素数）"
    find(x):要素xの属するグループの根を返す
    size(x):要素xの属するグループの要素数を返す
    same(x,y):x,yが同じグループに属しているか返す
    members(x):要素xが属するグループに属する要素をリストで返す
    roots(x):全ての根の要素を返す
    group_counte():グループの数を返す
    all_group_members():{根要素：[そのグループに含まれる要素のリスト]}の辞書を返す
    """
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

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

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

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

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

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

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    
def Kruskal(V,edges):
        """
        V:node数
        edges:[u,v,cost]の辺のリスト
        
        return: 最小全域木のコストの和
        """
        
        res = 0
        uf=UnionFind(V)
        for e in edges:
            if not uf.same(e[0], e[1]):
                uf.union(e[0], e[1])
                res += e[2]
        return res



N,M=map(int,input().split())
edges=[]

for i in range(M):
    x,y,z=map(int,input().split())
    edges.append((x-1,y-1,1))
    
E=Kruskal(N,edges)
print(N-E)

Solution (Python):
import sys
import numpy as np
sys.setrecursionlimit(10 ** 7)

sr = lambda: sys.stdin.readline().rstrip()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))

N, M = lr()


def find(A, x):
    p = A[x]
    if p == x:
        return x
    a = find(A, p)
    A[x] = a
    return a


def union(A, x, y):
    if find(A, x) > find(A, y):
        bx, by = find(A, y), find(A, x)
    else:
        bx, by = find(A, x), find(A, y)
    
    A[by] = bx

V = [i for i in range(N)]
for i in range(M):
    x, y, z = lr()
    if find(V, x-1) != find(V, y-1):
        union(V, x-1, y-1)

answer = [find(V, x) for x in set(V)]
print(len(set(answer)))

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

def f(j):
  a[j]=1
  n=len(dic[j])
  for k in range(n):
    if a[dic[j][k]]==0:
      f(dic[j][k])

N, M=map(int, input().split())
dic={}
for i in range(1, N+1):
  dic[i]=[]

for i in range(M):
  x, y, z=map(int, input().split())
  dic[x].append(y)
  dic[y].append(x)
  
a=[0]*(N+1)
out=0
i=1
while i<N+1:
  if a[i]==0:
    a[i]=1
    out+=1
    n=len(dic[i])
    for j in range(n):
      if a[dic[i][j]]==0:
        f(dic[i][j])
  i+=1
print(out)

Solution (Python):
from collections import Counter,defaultdict,deque
from heapq import heappop,heappush,heapify
import sys,bisect,math,itertools,pprint,fractions
sys.setrecursionlimit(10**8)
mod = 10**9+7
mod2 = 998244353
INF = float('inf')
def inp(): return int(sys.stdin.readline())
def inpl(): return list(map(int, sys.stdin.readline().split()))
def inpln(n): return list(int(sys.stdin.readline()) for i in range(n))

n,m = inpl()
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

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

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

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

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

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

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]
        
    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())


uf = UnionFind(n)
for i in range(m):
    a,b,c = inpl()
    uf.union(a-1,b-1)
print(uf.group_count())

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

class Union:
  def __init__(self, num):
    self.T = [-1 for i in range(num)]

  def root(self, x):
    if self.T[x] < 0: return x
    return self.root(self.T[x])

  def size(self, x):
    return -self.T[self.root(x)]

  def merge(self, x, y):
    a = self.root(x)
    b = self.root(y)
    if a == b: return False
    if self.size(a) < self.size(b): a, b = b, a
    self.T[a] += self.T[b]
    self.T[b] = a
    return True

uni = Union(N)

for i in range(M):
  x, y, z = XYZ[i]
  x -= 1
  y -= 1
  z -= 1
  uni.merge(x, y)

ans = 0
for i in range(N):
  if uni.T[i] < 0:
    ans += 1

print(ans)

Solution (Python):
import sys
def input():
    return sys.stdin.readline()[:-1]
n,m=map(int,input().split())
xyz=[list(map(int,input().split())) for i in range(m)]

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


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

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

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

    def diff(self, x, y):
        return self.weight[x] - self.weight[y]

uf=WeightedUnionFind(n)
for i in range(m):
    uf.union(xyz[i][0] ,xyz[i][1],1)

dic={}
for i in range(n):
    tmp=uf.find(i+1)
    if tmp in dic:
        continue
    else:
        dic[tmp]=1

print(len(dic.values()))

Solution (Python):
def rt(i):
    while i!=G[i][0]:
        i = G[i][0]
    return i
N,M = map(int,input().split())
G = {i:[i,1] for i in range(1,N+1)}
for _ in range(M):
    X,Y,Z = map(int,input().split())
    rx = rt(X)
    ry = rt(Y)
    if rx!=ry:
        if G[rx][1]>=G[ry][1]:
            G[ry][0] = rx
            G[rx][1] += G[ry][1]
        else:
            G[rx][0] = ry
            G[ry][1] += G[rx][1]
cnt = 0
A = []
for i in range(1,N+1):
    A.append(rt(i))
A = list(set(A))
print(len(A))

Solution (Python):

from collections import defaultdict,deque
from heapq import heappush, heappop
from itertools import permutations
import sys
import math
import bisect
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS():return [list(x) for x in sys.stdin.readline().split()]
def S():
    res = list(sys.stdin.readline())
    if res[-1] == "\n":
        return res[:-1]
    return res
def IR(n):
    return [I() for i in range(n)]
def LIR(n):
    return [LI() for i in range(n)]
def SR(n):
    return [S() for i in range(n)]
def LSR(n):
    return [LS() for i in range(n)]

sys.setrecursionlimit(1000000)
mod = 1000000007

def solve():
    def root(x):
        if par[x] == x:
            return x
        par[x] = root(par[x])
        return par[x]
    def unite(x,y):
        x = root(x)
        y = root(y)
        if rank[x] < rank[y]:
            par[x] = y
        else:
            par[y] = x
            if rank[x] == rank[y]:
                rank[x] += 1
    n,m = LI()
    par = [i for i in range(n)]
    rank = [0]*n
    for i in range(m):
        x,y,z = LI()
        x -= 1
        y -= 1
        if root(x) != root(y):
            unite(x,y)
    s = set([root(i) for i in range(n)])
    print(len(s))
    return


if __name__ == "__main__":
    solve()

Solution (Python):
N,M=map(int,input().split())
xyz=[tuple(map(int,input().split())) for i in range(M)]
class unionFind:
    parent = []
    num=0
    def __init__(self, N):
        self.parent = [i for i in range(N)]
        self.num=N
    def root(self, x):
        if self.parent[x] == x:
            return(x)
        else:
            self.parent[x] = self.root(self.parent[x])
            return(self.parent[x])

    def same(self, x, y):
        x, y = x-1, y-1
        return(self.root(x) == self.root(y))

    def unite(self, x, y):
        x, y = x-1, y-1
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return
        else:
            self.parent[x] = y
            self.num-=1
            return
G=unionFind(N)
for x,y,z in xyz:
  G.unite(x,y)
print(G.num)

Solution (Python):
N, M = map(int, input().split())

par = [i for i in range(N)]
rank = [0 for i in range(N)]


def get_root(A):
    if par[A] == A:
        return A
    par[A] = get_root(par[A])
    return par[A]


def connect(A, B):
    A = get_root(A)
    B = get_root(B)
    if rank[A] < rank[B]:
        par[A] = B
    else:
        par[B] = A
        if rank[A] == rank[B]:
            rank[A] += 1


def verify_connect(A, B):
    if get_root(A) == get_root(B):
        return True
    else:
        return False


for i in range(M):
    x, y, z = map(int, input().split())
    connect(x-1, y-1)
ans = 0
for i in range(N):
    if i == get_root(i):
        ans += 1

print(ans)

Solution (Python):


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

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

searched = [False] * N
count = 0
for i in range(N):
	if searched[i] == True:
		continue

	count += 1
	stack = [i]
	searched[i] = True
	while len(stack) > 0:
		node = stack.pop()	
		for n in adj_list[node]:
			if searched[n] == False:
				stack.append(n)
				searched[n] = True

print(count)

Solution (Python):
N, M = map(int, input().split())
ABZ = [list(map(int, input().split())) for _ in range(M)]
 
root = [i for i in range(N + 1)]
comp_size = [1] * (N+1)
 
def root_find(x):
  y = root[x]
  if x == y:
    return x
  else:
    z = root_find(y)
    root[x] = z
    return z

def merge(x, y):
  
  rx = root_find(x)
  ry = root_find(y)
  sx = comp_size[rx]
  sy = comp_size[ry]
  if rx == ry:
    return 0
  else:
    if sx >= sy:
      root[ry] = rx
      comp_size[rx] = sx + sy
    else:
      root[rx] = ry
      comp_size[ry] = sx + sy
    return sx * sy

for a, b, z in ABZ:
  merge(a, b)


check = [0] * (N + 1)
answer = 0
for i in range(1, N + 1):
  ri = root_find(i)
  if check[ri] == 0:
    answer += 1
    check[ri] = 1

print(answer)

Solution (Python):


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


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


def unite(a, b):
    a = find(a)
    b = find(b)
    if a == b:
        return False
    else:
        if par[a] < par[b]:
            a, b = b, a
        par[a] += par[b]
        par[b] = a
        return True


for i in range(m):
    x, y, z = map(int, input().split())
    unite(x, y)
cnt = 0
for i in range(n):
    if par[i + 1] < 0:
        cnt += 1
print(cnt)