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.v = [-1 for _ in range(n)]

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

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if -self.v[x] < -self.v[y]:
            x, y = y, x
        self.v[x] += self.v[y]
        self.v[y] = x

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

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

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


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

    if z & 1:
        uf.unite(x + N, y)
        uf.unite(x, y + N)
    else:
        uf.unite(x, y)
        uf.unite(x + N, y + N)
print(sum(1 for i in range(N) if uf.root(i)))

Solution (Python):
from queue import Queue

N, M = map(int, input().split())
d = {}
for i in range(1, N+1):
    d[i] = []
for i in range(M):
    x, y, z = map(int, input().split())
    d[x].append(y)
    d[y].append(x)

isChecked = [False for i in range(N)]
ans = 0
for k in d:
    if isChecked[k-1]:
        continue
    ans += 1
    q = Queue()
    q.put(k)
    while not q.empty():
        v = q.get()
        if isChecked[v-1]:
            continue
        isChecked[v-1] = True
        for u in d[v]:
            q.put(u)

print(ans)

Solution (Python):
r=lambda x:x*(u[x]<0)or r(u[x])
i=lambda:map(int,input().split()[:2])
n,m=i()
u=[-1]*-~n
while m:
 x,y=sorted(map(r,i()));m-=1
 if x!=y:u[x]+=u[y];u[y]=x
print(sum(i<0for i in u)-1)

Solution (Python):
r=lambda x:x*(u[x]<0)or r(u[x])
n,m,*t=map(int,open(0).read().split())
u=[-1]*-~n
for x,y in zip(t[::3],t[1::3]):
 x,y=sorted((r(x),r(y)))
 if x!=y:u[x]+=u[y];u[y]=x
print(sum(i<0for i in u)-1)

Solution (Python):
r=lambda x:x if u[x]<0else r(u[x])
n,m,*t=map(int,open(0).read().split())
u=[-1]*-~n
for x,y in zip(t[::3],t[1::3]):
 x,y=sorted((r(x),r(y)))
 if x!=y:u[x]+=u[y];u[y]=x
print(sum(i<0for i in u)-1)

Solution (Python):
r=lambda x:x if u[x]<0else r(u[x])
n,m,*t=map(int,open(0).read().split())
u=[-1]*-~n
for x,y in zip(t[::3],t[1::3]):
 x,y=sorted((r(x),r(y)))
 if x!=y:u[x]+=u[y];u[y]=x
print(sum(i<0for i in u)-1)

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

n, m = map(int, input().split())
xyz = [[] for i in range(n+1)]
for _ in range(m):
    x, y, z = map(int, input().split())
    xyz[x].append(y)
    xyz[y].append(x)
    
ans = 0
visited = [False]*(n+1)
def dfs(x):
    visited[x] = True
    for y in xyz[x]:
        if not visited[y]:
            dfs(y)

for x in range(1, n+1):
    if visited[x]:
        continue
    dfs(x)
    ans += 1
    

print(ans)

Solution (Python):
class UnionFind():
    def __init__(self,size):
        self.table=[-1]*size
    def root(self,x):
        while self.table[x]>=0:
            x=self.table[x]
        return x
    def unite(self,x,y):
        s1=self.root(x)
        s2=self.root(y)
        if s1!=s2:
            if self.table[s1]>self.table[s2]:
                s1,s2=s2,s1
            self.table[s1]+=self.table[s2]
            self.table[s2]=s1
        return
    def same(self,x,y):
        return self.root(x)==self.root(y)
    def size(self,x):
        return -self.table[self.root(x)]
n,m,*t=map(int,open(0).read().split())
u=UnionFind(n+1)
for x,y in zip(t[::3],t[1::3]):
    u.unite(x,y)
print(sum(i<0for i in u.table)-1)

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

N, M = map(int,input().split())
E = [[] for k in range(N)]

for k in range(M):
    X, Y, Z = map(int,input().split())
    E[X-1].append(Y-1)
    E[Y-1].append(X-1)
G = [-1]*N

def dfs(now,group):
    if G[now] == -1:
        G[now] = group
        for tsugi in E[now]:
            dfs(tsugi,group)

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

Solution (Python):
from collections import deque

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


uf = [-1]*(n+1)
def find(i):
    if uf[i] < 0:
        return i
    else:
        uf[i] = find(uf[i])
        return uf[i]

for x, y, z in xyz:
    px, py = find(x), find(y)
    
    if px != py:
        px, py = (px, py) if uf[py] < uf[px] else (px, py)
        uf[px] += uf[py]
        uf[py] = px


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

Solution (Python):
from collections import deque

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


uf = [-1]*(n+1)
def find(i):
    if uf[i] < 0:
        return i
    else:
        uf[i] = find(uf[i])
        return uf[i]

for x, y, z in xyz:
    px, py = find(x), find(y)
    
    if px != py:
        px, py = (px, py) if uf[py] < uf[px] else (px, py)
        uf[px] += uf[py]
        uf[py] = px


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

Solution (Python):
from collections import deque

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

connects = [0]*(n+1)
group = 1
for i in range(1, n+1):
    if connects[i] > 0:
        continue
    if len(xyz[i]) == 0:
        connects[i] = group
        group += 1
        continue

    que = deque(xyz[i])
    connects[i] = group
    while len(que) > 0:
        x, y, z = que.popleft()
        connects[y] = group
        for xn, yn, zn in xyz[y]:
            if connects[yn] > 0:
                pass
            else:
                que.append((xn, yn, zn))
    group += 1
    

print(max(connects))

Solution (Python):
from collections import defaultdict, deque
def inpl(): return list(map(int, input().split()))

class UnionFind():

    def __init__(self, N):
        self.parent = [-1] * (N+1)
        self.size = [1] * (N+1)

    def find(self, x):
        if self.parent[x] == -1:
            return x
        else:
            self.parent[x] = self.find(self.parent[x])
            return self.parent[x]

    def unite(self, x, y):
        x_p = self.find(x)
        y_p = self.find(y)
        if x_p != y_p:
            if self.size[x_p] < self.size[y_p]:
                x_p, y_p = y_p, x_p
            self.size[x_p] += self.size[y_p]
            self.parent[y_p] = x_p

N, M = inpl()
UFT = UnionFind(N)

for _ in range(M):
    x, y, z = inpl()
    UFT.unite(x, y)

print(UFT.parent[1:].count(-1))

Solution (Python):



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

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

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

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

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

        self.grp-=1
        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 group_num(self):
        return self.grp


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(uf.grp)

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

class UnionFind():
    def __init__(self,n):
        self.parent = [-1 for _ in range(n)]

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

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

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

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

un = UnionFind(N)
cnt = 0
for i in XYZ:
    un.unite(i[0]-1,i[1]-1)
for i in un.parent:
    if(i<0):
        cnt+=1
print(cnt)

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

N,M=map(int, raw_input().split())
par=[ i for i in range(N+1)  ]

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

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

def unite(x,y):
	x=root(x)
	y=root(y)
	if x==y: return
	par[x]=y


for i in range(M):
	x,y,z=map(int, raw_input().split())
	unite(x,y)


S=set()
for i in range(1,N+1):
	S.add(root(i))

print len(S)

Solution (Python):


import sys
sys.setrecursionlimit(1000000)

def get_root(start, parents):
    if parents[start] == -1:
        return start
    else:
        return get_root(parents[start], parents)

def main():
    n, m = list(map(int, input().split()))
    parents = [-1] * (n + 1)
    for _ in range(m):
        x, y, z = list(map(int, input().split()))
        if parents[x] == -1 and parents[y] == -1:
            parents[y] = x
        elif parents[x] == -1:
            root_y = get_root(y, parents)
            if root_y != x:
                parents[x] = y
        elif parents[y] == -1:
            root_x = get_root(x, parents)
            if root_x != y:
                parents[y] = x
        else:
            root_x = get_root(x, parents)
            root_y = get_root(y, parents)
            if root_x != root_y:
                parents[root_y] = root_x
    print(len([0 for p in parents[1:] if p == -1]))


if __name__ == '__main__':
    main()

Solution (Python):

import sys

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

    
    def num_graph(self):
        return len([i for i in self.par[1:] if i < 0])

    
    def find(self, x):
        
        if(self.par[x] < 0):
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.find(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 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.num_graph())

    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):

import sys

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

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

    ans = len([i for i in uf.par[1:] if i < 0])

    print(ans)

    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):
import sys


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

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

    def unite(self, x, y):
        if self.is_same(x, y):
            return
        rx = self.find(x)
        ry = self.find(y)
        if self.rank[rx] < self.rank[ry]:
            self.root[rx] = ry
        else:
            self.root[ry] = rx
            if self.rank[rx] == self.rank[ry]:
                self.rank[rx] += 1

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

def main():
    input = sys.stdin.readline
    N, M = map(int, input().split())
    uft = UnionFind(N)
    for _ in range(M):
        x, y, _ = map(int, input().split())
        uft.unite(x, y)

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

    return len(root)


if __name__ == '__main__':
    print(main())

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)]
        self.size = [1 for _ in range(n)]

    def find(self, x):
        """
        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 と 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
            self.size[x] += self.size[y]

    def is_same(self, x, y):
        """
        x と y が同じグループか否か
        """
        return self.find(x) == self.find(y)

    def get_size(self, x):
        """
        x が属するグループの要素数
        """
        x = self.find(x)
        return self.size[x]


n, m = map(int, input().split())
a = [list(map(int, input().split())) for i in range(m)]
uf = UnionFind(n)
b = []
for i in a:
    uf.union(i[0]-1,i[1]-1)
for i in range(n):
  b.append(uf.find(i))
print(len(list(set(b))))

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)]
        self.size = [1 for _ in range(n)]

    def find(self, x):
        """
        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 と 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
            self.size[x] += self.size[y]

    def is_same(self, x, y):
        """
        x と y が同じグループか否か
        """
        return self.find(x) == self.find(y)

    def get_size(self, x):
        """
        x が属するグループの要素数
        """
        x = self.find(x)
        return self.size[x]


n, m = map(int, input().split())
a = [list(map(int, input().split())) for i in range(m)]
uf = UnionFind(n)
b = []
for i in a:
    uf.union(i[0]-1,i[1]-1)
for i in range(n):
  b.append(uf.find(i))
print(len(list(set(b))))

Solution (Python):
N, M = map(int, input().split())
nodes = [i for i in range(N)]


def root(x):
    if nodes[x] == x:
        return x
    else:
        nodes[x] = root(nodes[x])
    return nodes[x]


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


def unite(x, y):
    if not same(x, y):
        nodes[root(x)] = root(y)


for _ in range(M):
    X, Y, Z = map(int, input().split())
    unite(X-1, Y-1)


ans = 0
for i in range(len(nodes)):
    if nodes[i] == i:
        ans += 1

print(ans)

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

pairs = [set() for i in range(N + 1)]
appeared = set()

for i in range(M):
	x, y, z = map(int, input().strip().split(" "))
	
	pairs[x].add(y)
	pairs[y].add(x)
	
	appeared.add(x)
	appeared.add(y)

count_not_appeared = N - len(appeared)

group_count = 0
while appeared:
	cur = appeared.pop()
	queue = [cur]
	while queue:
		cur = queue.pop()
		for n in pairs[cur]:
			if n in appeared:
				appeared.remove(n)
				queue.append(n)
	group_count += 1

print(count_not_appeared + group_count)

Solution (Python):
class UFT(): 
    def __init__(self, N): 
        self.tree = [int(i) for i in range(N)] 
        self.rank = [0 for i in range(N)]

    def find(self, a):
        if self.tree[a] == a: return a
        else:
            self.tree[a] = self.find(self.tree[a])
            return self.tree[a]

    def unite(self, a, b):
        a = self.find(a)
        b = self.find(b)
        if a == b: return
        if self.rank[a] < self.rank[b]: self.tree[a] = b
        else:
            self.tree[b] = a
            if self.rank[a] == self.rank[b]: self.rank[a] += 1

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

print(len(set(parent.tree)))

Solution (Python):
def find(x):
    if root[x] == x:
        return x
    else:
        root[x] = find(root[x])
        return root[x]

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

def unite(x,y):
    x = find(x)
    y = find(y)
    if rank[x] == rank[y]:
        root[y] = x
        rank[x] += 1
    elif rank[x] > rank[y]:
        root[y] = x
    elif rank[x] < rank[y]:
        root[x] = y
    
n,m = map(int, input().split())
root = [i for i in range(n)]
rank = [0 for i in range(n)]

for i in range(m):
    x, y, z = [int(i)-1 for i in input().split()]
    if not same(x,y):
        unite(x,y)
    
for i in range(n):
    find(i)

print(len(list(set(root))))

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,input().split())
uni = UnionFind(n-1)

for i in range(m):
    a,b,c=map(int,input().split())
    a-=1
    b-=1
    uni.union(a,b)
t = set([])
for i in range(n):
    p = uni.find(i)
    t.add(p)
print(len(t))

Solution (Python):
n, m = map(int, input().split())
xyz = [tuple(int(x) - 1 for x in input().split()) for _ in range(m)]


class UnionFind:
    def __init__(self, N):
        self.p = list(range(N))
        self.rank = [0] * N
        self.size = [1] * N

    def find_root(self, x):
        if self.p[x] != x:
            self.p[x] = self.find_root(self.p[x])

        return self.p[x]

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

    def unite(self, x, y):
        u = self.find_root(x)
        v = self.find_root(y)

        if u == v: return

        if self.rank[u] < self.rank[v]:
            self.p[u] = v
            self.size[v] += self.size[u]
            self.size[u] = 0
        else:
            self.p[v] = u
            self.size[u] += self.size[v]
            self.size[v] = 0

            if self.rank[u] == self.rank[v]:
                self.rank[u] += 1

    def get_size(self, x):
        return self.size[self.find_root(x)]

uft = UnionFind(n)
for x, y, z in xyz:
    uft.unite(x, y)

p = set()
for i in range(n):
    p.add(uft.find_root(i))

print(len(p))

Solution (Python):
def root(x):
    if par[x] == x:
        return x
    else:
        par[x] = root(par[x])
        return par[x]

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

def unite(x, y):
    x = root(x)
    y = root(y)
    if rank[x] == rank[y]:
        par[y] = x
        rank[x] += 1
    elif rank[x] > rank[y]:
        par[y] = x
    elif rank[x] < rank[y]:
        par[x] = y
    
N, M = map(int, input().split())
par = [i for i in range(N)]
rank = [0 for i in range(N)]

for i in range(M):
    x, y, z = map(int, input().split())
    x -= 1
    y -= 1
    if not same(x, y):
        unite(x, y)
    
for i in range(N):
    root(i)

par = list(set(par))
print(len(par))

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

def connected_components(graph):
    seen = set()
    def component(n):
        nodes = set([n])
        while nodes:
            n = nodes.pop()
            seen.add(n)
            nodes |= set(graph[n]) - seen
            yield n
    for n in graph:
        if n not in seen:
            yield component(n)

def print_gen(gen):
    a = [list(x) for x in gen]
    print(len(a))

print_gen(connected_components(g))

Solution (Python):
import math, string, itertools, fractions, heapq, collections, re, array, bisect, sys, copy, functools, random
from collections import deque, defaultdict, Counter; from heapq import heappush, heappop
from itertools import permutations, combinations, product, accumulate, groupby
from bisect import bisect_left, bisect_right, insort_left, insort_right; sys.setrecursionlimit(10 ** 7)
inf = 10 ** 20; INF = float("INF"); ans = 0; tmp = 0; ansli = []; tmpli = []; candili = []
eps = 1.0 / 10 ** 10; mod = 10 ** 9 + 7
dd = [(-1, 0), (0, 1), (1, 0), (0, -1)]; ddn = dd + [(-1, 1), (1, 1), (1, -1), (-1, -1)]; ddn9 = ddn + [(0, 0)]
"""for dx, dy in dd:
        nx = j + dx; ny = i + dy
            if 0 <= nx < w and 0 <= ny < h:"""
def wi(): return list(map(int, sys.stdin.readline().split()))
def wip(): return [int(x) - 1 for x in sys.stdin.readline().split()]
def ws(): return sys.stdin.readline().split()
def i(): return int(sys.stdin.readline())
def s(): return input()
def hi(n): return [i() for _ in range(n)]
def hs(n): return [s() for _ in range(n)]
def mi(n): return [wi() for _ in range(n)]
def mip(n): return [wip() for _ in range(n)]
def ms(n): return [ws() for _ in range(n)]

n, m = wi()

w = mi(m)

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


    
    
    def find(self, x):
        if self.par[x] < 0:
            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.par[x] < self.par[y]:
                self.par[y] += self.par[x]
                self.par[x] = y
            else:
                self.par[x] += self.par[y]
                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 size(self, x):
        return -self.par[self.find(x)]
u = UnionFind(n)
for i in range(m):
    u.union(w[i][0], w[i][1])

se = set()
for i in range(1, n + 1):
    se.add(u.find(i))


print(len(se))

Solution (Python):
import sys
 
 
class UnionFind:
    def __init__(self, n):
        self.table = [-1] * n
 
    def _root(self, x):
        if self.table[x] < 0:
            return x
        else:
            self.table[x] = self._root(self.table[x])
            return self.table[x]
 
    def find(self, x, y):
        return self._root(x) == self._root(y)
 
    def union(self, x, y):
        r1 = self._root(x)
        r2 = self._root(y)
        if r1 == r2:
            return
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            if d1 == d2:
                self.table[r1] -= 1
        else:
            self.table[r1] = r2
 
 
n, m = map(int, input().split())
uft = UnionFind(n)
for line in sys.stdin:
    x, y, z = map(int, line.split())
    x -= 1
    y -= 1
    uft.union(x, y)
 
ans = 0
for v in uft.table:
    if v < 0:
        ans += 1
print(ans)

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


    

    
    def find(x):
        if par[x] < 0:
            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 False
        else:
            
            if par[x] > par[y]:
                x,y = y,x
            par[x] += par[y]
            par[y] = x
            return True

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

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

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

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

if __name__ == '__main__':
    main()

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,input().split())
a=UnionFind(N)
for i in range(M):
    X,Y,Z=map(int,input().split())
    if a.same_check(X,Y):
        pass
    else:
        a.union(X,Y)
answer=set()
for i in range(1,N+1):
    answer.add(a.find(i))
print(len(answer))

Solution (Python):

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


par = [-1]*n


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

def unite(x,y):
    x = find(x)
    y = find(y)
    
    if x != y:
        
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x


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

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

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

Solution (Python):
import sys

class UnionFind():
    def __init__(self, n):
        self.parent = [-1] * n
        
    def root(self, x):
        '''
        Returns index of the root of the union to which x belongs to.
        '''

        if self.parent[x] < 0:
            return x

        else:
            self.parent[x] = self.root(self.parent[x])
            return self.parent[x]

    def size(self, x):
        '''
        Returns the size of the union to which input index belongs.
        '''
        
        return -1 * self.parent[self.root(x)]
    
    def unite(self, x, y):
        '''
        Unite two vertices x and y.\n
        Input:
            x and y: indices of vertices to unite.
        '''

        x, y = self.root(x), self.root(y)

        if x == y:
            return False

        else:
            size_x = - self.size(x)
            size_y = - self.size(y)

            if size_x > size_y:
                x, y = y, x

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

            return True


input = sys.stdin.readline
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.unite(x,y)

roots = set()

for i in range(N):
    
    roots.add(uf.root(i))

print(len(roots))

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