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):
import sys
sys.setrecursionlimit(200000)

class UnionFind:
    def __init__(self,N):
        self.par = [i for i in range(N)]
 
    def root(self,x):
        if self.par[x] == x:
            return x
        self.par[x] = self.root(self.par[x])
        return self.par[x]
 
    def unite(self,x,y):
        self.rx = self.root(x)
        self.ry = self.root(y)
        if self.rx == self.ry:
            return
        self.par[self.rx] = self.ry
 
    def same(self,x,y):
        self.rx = self.root(x)
        self.ry = self.root(y)
        return self.rx == self.ry
 
N,M = [int(i) for i in input().split()]
uf = UnionFind(N)
 
for _ in range(M):
    x,y,_ = [int(i)-1 for i in input().split()]
    uf.unite(x,y)
 
ans = set()
for i in range(N):
    ans.add(uf.root(i))
 
print(len(ans))

Solution (Python):
import sys

input = sys.stdin.readline
N, M = map(int, input().split())
pair = {}
rank = {}
def root(x):
    if x == pair[x]:
        return x
    else:
        pair[x] = root(pair[x])
    return pair[x]

def unite(x, y):
    rx = root(x)
    ry = root(y)
    if rx == ry:
      return
    if rx > ry:
        pair[rx] = pair[ry]
    else:
        pair[ry] = pair[rx]

def same(x, y):
    rx = root(x)
    ry = root(y)
    return rx == ry

for i in range(1, N+1):
    pair.setdefault(i, i)

for i in range(1, N+1):
    rank.setdefault(i, 0)

for i in range(M):
    x, y, z = map(int, input().split())
    if not same(x, y):
        if x < y:
            unite(x, y)
        else:
            unite(y, x)
cnt = set()
for k, y in pair.items():
    y = root(y)
    cnt.add(y)
print(len(cnt))

Solution (Python):
class UnionFind:

    def __init__(self, n: int):
        self._n = n
        self._parents = [i for i in range(n)]
        self._rank = [1 for _ in range(n)]

    def unite(self, x: int, y: int) -> None:
        px = self.find(x)
        py = self.find(y)

        
        if px != py:
            self._link(px, py)

    def _link(self, x: int, y: int):
        if self._rank[x] < self._rank[y]:
            self._parents[x] = y
        elif self._rank[x] > self._rank[y]:
            self._parents[y] = x
        else:
            self._parents[x] = y
            self._rank[y] += 1

    def same(self, x: int, y: int) -> bool:
        px = self.find(x)
        py = self.find(y)
        return px == py

    def find(self, x: int) -> int:
        if self._parents[x] == x:
            return x

        self._parents[x] = self.find(self._parents[x])
        return self._parents[x]



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

uf = UnionFind(n)

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

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

print(len(s))

Solution (Python):
import sys

input = sys.stdin.readline
N, M = map(int, input().split())
pair = {}
rank = {}
def root(x):
    if x == pair[x]:
        return x
    else:
        pair[x] = root(pair[x])
    return pair[x]

def unite(x, y):
    rx = root(x)
    ry = root(y)
    if rx > ry:
        pair[rx] = pair[ry]
    else:
        pair[ry] = pair[rx]

for i in range(1, N+1):
    pair.setdefault(i, i)

for i in range(1, N+1):
    rank.setdefault(i, 0)

for i in range(M):
    x, y, z = map(int, input().split())
    if x < y:
        unite(x, y)
    else:
        unite(y, x)

cnt = set()
for k, y in pair.items():
    y = root(y)
    cnt.add(y)
print(len(cnt))

Solution (Python):
import sys

input = sys.stdin.readline
N, M = map(int, input().split())
pair = {}
rank = {}
def root(x):
    if x == pair[x]:
        return x
    else:
        pair[x] = root(pair[x])
    return pair[x]

def unite(x, y):
    rx = root(x)
    ry = root(y)
    if rx > ry:
        pair[rx] = pair[ry]
    else:
        pair[ry] = pair[rx]

for i in range(1, N+1):
    pair.setdefault(i, i)

for i in range(1, N+1):
    rank.setdefault(i, 0)

tmp = []
for i in range(M):
    tmp.append(list(map(int, input().split())))
tmp.sort()
for i in range(M):
    x, y = tmp[i][0], tmp[i][1]
    if x < y:
        unite(x, y)
    else:
        unite(y, x)

cnt = set()
for k, y in pair.items():
    y = root(y)
    cnt.add(y)
print(len(cnt))

Solution (Python):




import sys

sys.setrecursionlimit(10**5+4)

def main():
    
    n, m = [int(s) for s in input().split()]
    to = [list() for _ in range(n)]
    for _ in range(m):
        x, y, _ = [int(s) for s in input().split()]
        x -= 1
        y -= 1
        to[x].append(y)
        to[y].append(x)
    
    colors = [None] * n
    counter = 0
    def dfs(cur, c):
        if colors[cur] != None:
            return
        colors[cur] = c
        for i in to[cur]:
            dfs(i, c)
    for i in range(n):
        if colors[i] == None:
            dfs(i, counter)
            counter += 1
    ans = counter
    
    print(ans)

if __name__ == '__main__':
    main()

Solution (Python):
import sys
sys.setrecursionlimit(10**7)
class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
 
    def root(self, i):
        if self.parent[i] == i:
            return i
        else:
            self.parent[i] = self.root(self.parent[i])
            return self.parent[i]
    
    def find(self, x, y):
        return self.root(x) == self.root(y)
 
    def union(self, i, j):
        i = self.root(i)
        j = self.root(j)
        self.parent[j] = i
N, M = map(int, input().split())
tree = UnionFind(N)
for _ in range(M):
    x, y, z = map(int, input().split())
    tree.union(x-1, y-1)
for i in range(N):
    tree.root(i)
print(len(set(tree.parent)))

Solution (Python):
import sys
import math 
ni = lambda: int(ns())
na = lambda: list(map(int, input().split()))
ns = lambda: input()

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

    def Tree_num(self):
        return self.root_num
    
    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
            self.root_num-=1

        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            self.root_num-=1
            
            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)]

N,M=na()
UF = UnionFind(N)
for i in range(M):
    x,y,z=na()
    UF.Unite(x,y)

print(UF.Tree_num())

Solution (Python):
N, M = map(int, input().split())
XYZ = []
for _ in range(M):
    x,y,z = map(int, input().split())
    XYZ.append((x,y,z))
    
pairs = XYZ[:]
known = [False] * (N)

pairs = sorted(pairs)


class UnionFind:
    def __init__(self, n):
        
        self.par = [i for i in range(n)] 
        self.rank = [0] * 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 is_group(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.par[x] = y
        else:
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1


def create_union(edges, v_num):
    
    
    u = UnionFind(v_num)
    for x,y in edges:
        u.union(x,y)
        
    return [u.find(x) for x in range(v_num)]
     
    
edges = [(x,y) for x,y,z in pairs]

parents = create_union(edges, N+1)
union = set()
for p in parents:
    union.add(p)
union_num = len(union) -1
print(union_num)

Solution (Python):

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

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

    def unite(self, x, y):
        root_x = self.get_root(x)
        root_y = self.get_root(y)
        
        
        
        if root_x != root_y:
            
            if self.nodes[root_x] < self.nodes[root_y]:
                big_root = root_x
                small_root = root_y
            else:
                small_root = root_x
                big_root = root_y
            self.nodes[big_root] += self.nodes[small_root]
            self.nodes[small_root] = big_root


N, M = map(int, input().split())
uf = UnionFind(N)
get_root, unite, nodes = uf.get_root, uf.unite, uf.nodes

for _ in range(M):
    x, y, _ = map(int, input().split())
    x -= 1
    y -= 1
    unite(x, y)
ans = 0
for i in range(N):
    if nodes[i] < 0:
        ans += 1
print(ans)

Solution (Python):

import sys
input = sys.stdin.readline
 
n,m = map(int,input().split())

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


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


def unite(x,y,par,rank):
    x = find(x,par)
    y = find(y,par)
    
    if x != y:
        
        if rank[x] < rank[y]:
            par[x] = y
        else:
            par[y] = x
            if rank[x]==rank[y]:
                rank[x] += 1


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

for i in range(m):
    X,Y,Z = map(int,input().split())
    unite(X-1,Y-1,par,rank)
 
tank = set([])
for i in range(n):
    p = find(i,par)
    tank.add(p)
print(len(tank))

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

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

class UnionFind():
    def __init__(self, N):
        self.nodes = [i for i in range(N)]

    def root(self, x):
        if self.nodes[x] != x:
            self.nodes[x] = self.root(self.nodes[x])
        return self.nodes[x]

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

    def unite(self, x, y):
        if self.same(x, y):
            return
        self.nodes[self.root(x)] = self.root(y)

uf = UnionFind(N)

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

group = set()
for node in uf.nodes:
    group.add(uf.root(node))

print(len(group))

Solution (Python):
import math
import functools
import itertools
import numpy as np
import sys
MAX_INT = int(10e10)
MIN_INT = -MAX_INT
mod = 1000000007
sys.setrecursionlimit(1000000)
def IL(): return list(map(int,input().split()))
def SL(): return input().split()
def I(): return int(sys.stdin.readline())
def S(): return input()


def init(n):
    for i in range(N):
        par[i]=i
        rnk[i]=0
def find(x):
    if par[x]==x:
        return x
    else:
        par[x]=find(par[x])
        return par[x]
def unite(x,y):
    x=find(x)
    y=find(y)
    if x==y:
        return
    if (rnk[x]<rnk[y]):
        par[x]=y
    else:
        par[y]=x
        if(rnk[x]==rnk[y]):
            rnk[x]+=1
def same(x,y):
    return find(x)==find(y)



N,M = IL()
xyz = [IL() for i in range(M)]

used = [False]*(N+1)

par=[0 for i in range(N+1)]
rnk=[0 for i in range(N+1)]

init(N)

for x,y,z in xyz:
    unite(x,y)

ans = 0
for i in range(1,N+1):
    if used[find(i)] == False:
        ans += 1
        used[find(i)] = True

print(ans)

Solution (Python):
class UnionFind():
    def __init__(self, N):
        self.N = N
        self.rank = [0] * N
        self.par = [i for i in range(N)]
        self.counter = [1] * 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 unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x != y:
            z = self.counter[x] + self.counter[y]
            self.counter[x], self.counter[y] = z, z
        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 size(self, x):
        x = self.find(x)
        return self.counter[x]

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

    def groups(self):
        group = set()
        for i in range(self.N):
            group.add(self.find(i))
        return len(group)


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

if N == 2:
    print(1)
    quit()


graph = UnionFind(N)
for i in range(M):
    x, y, z = map(int, input().split())
    graph.unite(x-1, y-1)

ans = graph.groups()
print(ans)

Solution (Python):
class UNION_FIND(object):
    def __init__(self,n):
        self.parent=[-1 for i in range(n)]
        
    def root(self,x):
        if self.parent[x]<0:
            return x
        else:
            self.parent[x]=self.root(self.parent[x])
            return self.parent[x]
 
    def size(self,x):
        return -self.parent[self.root(x)]
    def union(self,x,y):
        x=self.root(x)
        y=self.root(y)
        if x==y:
            return False
        if self.size(x)<self.size(y):
            x,y=y,x
        self.parent[x]+=self.parent[y]  
        self.parent[y]=x   
        return True
n,m=map(int,input().split())
u=UNION_FIND(n)
for i in range(m):
    a,b,c=map(int,input().split())
    u.union(a-1,b-1)
ans=0
for i in u.parent:
    if i<0:
        ans+=1
    
print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n)]
        self.rank = [0] * (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 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

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

for i in range(m):
  x,y,z=map(int,input().split())
  U.union(x-1,y-1)
ans=0
for i,j in enumerate(U.par):
  if i==j:
    ans+=1
print(ans)

Solution (Python):
def union_find():
    
    def get_parent(node):
        if par[node] == -1:
            return node
        else:
            par[node] = get_parent(par[node])
            return par[node]

    def merge(i, j):
        i = get_parent(i)
        j = get_parent(j)
        if i != j:
            par[j] = i
        return

    n, m = map(int, input().split())
    xyz = [list(map(int, input().split())) for _ in range(m)]
    par = [-1] * n
    for x, y, z in xyz:
        merge(x-1, y-1)
    print(par.count(-1))

union_find()

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):
'''input
100000 1
1 100000 100
'''
import sys
sys.setrecursionlimit(100100)
N, M = [int(x) for x in input().split()]

vien = [[] for _ in range(N)]

for _ in range(M):
	a, b, w = [int(x) for x in input().split()]
	a -= 1
	b -= 1
	w = w & 1
	vien[a].append(b)
	vien[b].append(a)

been = [False]*N
ats = 0
def dfs(x):
	been[x] = True
	for u in vien[x]:
		if not been[u]:
			dfs(u)


for i in range(N):
	if been[i]: continue

	ats += 1
	dfs(i)

print(ats)

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

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

    def merge(self, x, y): 
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.parent[x] > self.parent[y]: 
            x,y=y,x
        self.parent[x] += self.parent[y] 
        self.parent[y] = x 
        return True

    def issame(self, x, y): 
        return self.root(x) == self.root(y)
        
    def size(self,x): 
        return -self.parent[self.root(x)]
        
        
n,m = [int(i) for i in input().split()]

T=UnionFind(n)
c=0
for _ in [0]*m:
    x,y,z=[int(i) for i in input().split()]
    if T.merge(x-1,y-1):
        c+=1

print(n-c)

Solution (Python):


import sys
sys.setrecursionlimit(10 ** 6)

class UnionFind(object):
    def __init__(self, n):
        self.parent = [i for i in range(n)]
        self.rank = [0 for _ in range(n)]
        self.size = [1 for _ in range(n)]
        self.components = n

    def find(self, x):
        if self.parent[x] == x:
            return x
        self.parent[x] = self.find(self.parent[x])
        return self.parent[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
            elif self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            self.parent[y] = x
            self.size[x] += self.size[y]
            self.components -= 1

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

    def getSize(self, x):
        return self.size(self.find(x))

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

edge = [] * M
uf = UnionFind(N)

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

print(uf.components)

Solution (Python):


class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.size = [1]*n 

    def root(self, x): 
        while self.parent[x] != x:
            self.parent[x] = self.parent[self.parent[x]]
            x = self.parent[x]
        return x 

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

    def issame(self, x, y): 
        return self.root(x) == self.root(y)
        
    def size(self,x): 
        return self.size[self.root(x)]


n,m = [int(i) for i in input().split()]
 
T=UnionFind(n)
c=0
for _ in [0]*m:
    x,y,z=[int(i) for i in input().split()]
    if T.merge(x-1,y-1):
        c+=1
 
print(n-c)

Solution (Python):


class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.size = [1]*n 

    def root(self, x): 
        while self.parent[x] != x:
            self.parent[x] = self.parent[self.parent[x]]
            x = self.parent[x]
        return x 

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

    def issame(self, x, y): 
        return self.root(x) == self.root(y)
        
    def size(self,x): 
        return self.size[self.root(x)]


n,m = [int(i) for i in input().split()]
 
T=UnionFind(n)
c=0
for _ in [0]*m:
    x,y,z=[int(i) for i in input().split()]
    if not T.issame(x-1,y-1):
        T.merge(x-1,y-1)
        c+=1
 
print(n-c)

Solution (Python):


class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.size = [1]*n 

    def root(self, x): 
        while self.parent[x] != x:
            self.parent[x] = self.parent[self.parent[x]]
            x = self.parent[x]
        return x 

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

    def issame(self, x, y): 
        return self.root(x) == self.root(y)
        
    def size(self,x): 
        return self.size[self.root(x)]


n,m = [int(i) for i in input().split()]
 
T=UnionFind(n)
c=0
for _ in [0]*m:
    x,y,z=[int(i) for i in input().split()]
    if not T.issame(x-1,y-1):
        T.merge(x-1,y-1)
        c+=1
 
print(n-c)

Solution (Python):


class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.size = [1]*n 

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

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

    def issame(self, x, y): 
        return self.root(x) == self.root(y)
        
    def size(self,x): 
        return self.size[self.root(x)]


n,m = [int(i) for i in input().split()]
 
T=UnionFind(n)
c=0
for _ in [0]*m:
    x,y,z=[int(i) for i in input().split()]
    if not T.issame(x-1,y-1):
        T.merge(x-1,y-1)
        c+=1
 
print(n-c)

Solution (Python):
N,M= map(int, input().split())
class UnionFind:
    def __init__(self, n):
        self.data = [-1] * n
    def union(self, x, y):
        x,y = self.root(x), self.root(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 root(self, x):
        if self.data[x] < 0 :
            return x
        self.data[x] = self.root(self.data[x])
        return self.data[x]
    def findSet(self, x, y):
        return self.root(x) == self.root(y)
uf = UnionFind(N)
for _ in range(M):
    x,y,z= map(int, input().split())
    x-=1
    y-=1
    uf.union(x,y)
visited = set()
ans = 0
for v in range(N):
    if uf.root(v) not in visited:
        ans +=1
    visited.add(uf.root(v))
print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n)]
        self.rank = [0]*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 unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        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(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.unite(x-1, y-1)
print(sum(uf.par[i] == i for i in range(n)))

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n)]
        self.rank = [0]*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 unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        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(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.unite(x-1, y-1)
print(len(set(uf.find(i) for i in range(n))))

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


class UnionFind():
    def __init__(self):
        self.__table = {}
        self.__size = defaultdict(lambda: 1)

    def __root(self, x):
        if x not in self.__table:
            self.__table[x] = x
        elif x != self.__table[x]:
            self.__table[x] = self.__root(self.__table[x])

        return self.__table[x]

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

    def union(self, x, y):
        x = self.__root(x)
        y = self.__root(y)
        if x != y:
            self.__size[y] += self.__size[x]
            self.__table[x] = y

    def size(self, x):
        return self.__size[self.__root(x)]

    def num_of_group(self):
        g = 0
        for k, v in self.__table.items():
            if k == v:
                g += 1
        return g


@mt
def slv(N, M, XYZ):
    uf = UnionFind()
    v = set()
    for x, y, _ in XYZ:
        uf.union(x, y)
        v.add(x)
        v.add(y)

    ans = uf.num_of_group() + N - len(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()

Solution (Python):
import sys
sys.setrecursionlimit(10**8)
N, M = map(int, input().split())
num_edges = M
edges = [list(map(int, input().split())) for i in range(num_edges)]
adj = [[] for i in range(N+1)]
for ed in edges:
    adj[ed[0]] += [[ed[1], ed[2]]]
    adj[ed[1]] += [[ed[0], ed[2]]]
col_list = [-1 for i in range(N+1)]

def recfun(v, col):
    col_list[v] = col 
    for ed in adj[v]: 
        if col_list[ed[0]] == -1: 
            recfun(ed[0], col) 
count = 0
for i in range(1, N+1):
    if col_list[i] == -1:
        count +=1
        recfun(i, count)
print(count)

Solution (Python):
import sys

sys.setrecursionlimit(10**6)

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

counter = 0
c = [-1 for i in range(n)]
p = [[] for n in range(n)]

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

def dfs(num, depth):
    if c[num] != -1:
        return
    else:
        c[num] = depth
    for i in p[num]:
        dfs(i, depth)

for i in range(n):
    if c[i] == -1:
        counter += 1
        dfs(i, counter)

print(max(c))

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

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



PARENT = list(range(N))

def root(n):
    if PARENT[n] == n:
        return n
    else:
        ret = root(PARENT[n])
        PARENT[n] = ret
        return ret

def same(n1, n2):
    return root(n1) == root(n2)

def unite(n1, n2):
    n1 = root(n1)
    n2 = root(n2)
    if n1 == n2:
        return
    PARENT[n1] = n2

used = set()

for i in range(M):
    x, y, z = [int(x) for x in input().split()]
    x -= 1
    y -= 1
    unite(x, y)
    used.add(x)
    used.add(y)

s = {root(u) for u in used}

cnt = len(s) + N - len(used)

print(cnt)

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

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



PARENT = list(range(N))

def root(n):
    if PARENT[n] == n:
        return n
    else:
        ret = root(PARENT[n])
        PARENT[n] = ret
        return ret

def same(n1, n2):
    return root(n1) == root(n2)

def unite(n1, n2):
    n1 = root(n1)
    n2 = root(n2)
    if n1 == n2:
        return
    PARENT[n1] = n2

used = set()

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

cnt = 0
for i,p in enumerate(PARENT):
    if root(p) == i:
        cnt += 1
print(cnt)

Solution (Python):



class UnionFind(object):

    def __init__(self, n):
        self.n = n
        self.parent = list(range(self.n))
        self.rank = [0]*n

    def find_parent(self, x):
        if self.parent[x] == x:
            return x
        else:
            self.parent[x] = self.find_parent(self.parent[x])
            return self.parent[x]

    def unite(self, x, y):
        x = self.find_parent(x)
        y = self.find_parent(y)
        if self.rank[x] < self.rank[y]:
            self.parent[x] = y
        else:
            self.parent[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1


N, M = map(int, input().split())
uf = UnionFind(N+1)

for _ in range(M):
    xx, yy, zz = map(int, input().split())
    uf.unite(xx, yy)

res = [0] * (N + 1)
res_c = 0
for i in range(1, N + 1):
    j = uf.find_parent(i)
    if res[j] == 0:
        res_c += 1
    res[j] += 1

print(N - (sum(res) - res_c))