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



Sample input:
3 1
1 2 1


Sample output:
2

Submission status: Accepted

Solution code:
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 20 20:47:47 2019

@author: Owner
"""

# -*- coding: utf-8 -*-
"""
Created on Sat Apr 13 09:53:12 2019

@author: Owner
"""
import numpy as np
import sys
import collections
import scipy.misc
import math
from operator import itemgetter
import itertools
import copy
import bisect

#素因数を並べる
def prime_decomposition(n):
  i = 2
  table = []
  while i * i <= n:
    while n % i == 0:
      n /= i
      table.append(int(i))
    i += 1
  if n > 1:
    table.append(int(n))
  return table   
# 桁数を吐く
def digit(i):
    if i > 0:
        return digit(i//10) + [i%10]
    else:
        return []
    
def getNearestValueIndex(list, num):
    """
    概要: リストからある値に最も近い値のインデックスを取得する関数
    @param list: データ配列
    @param num: 対象値
    @return 対象値に最も近い値
    """

    # リスト要素と対象値の差分を計算し最小値のインデックスを取得
    idx = np.abs(np.asarray(list) - num).argmin()
    return idx

def find_index(l, x, default=False):
    if x in l:
        return l.index(x)
    else:
        return default


"""
N, X = map(int, input().split())

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

P = [0]*N
Y = [0]*N
for n in range(N):
    P[n], Y[n] = map(int, input().split())

# 多次元配列の宣言（あとでintにすること。）（タプルにすること。）
dp = np.zeros((N+1, 4,4,4))
    
all(nstr.count(c) for c in '753')

# 複数配列を並び替え
ABT = zip(A, B, totAB)
result = 0
# itemgetterには何番目の配列をキーにしたいか渡します
sorted(ABT,key=itemgetter(2))
A, B, totAB = zip(*ABT)
A.sort(reverse=True)

# 2進数のbit判定
(x >> i) & 1

# dp最小化問題
dp = [np.inf]*N
for n in range(N):
    if n == 0:
        dp[n] = 0
    else:
        for k in range(1,K+1):
            if n-k >= 0:
                dp[n] = min(dp[n], dp[n-k] + abs(h[n]-h[n-k]))
            else:
                break
# 累積和
add = 1 # 問題によって決まる
res = 0
sums = [0]*(len(nums)+1)
for i in range(len(nums)):
    sums[i+1] = sums[i] + nums[i]
for i in range(0, len(nums), 2):
    left = i
    right = min(i+add, len(nums))
    tmp = sums[right] - sums[left]
    res = max(tmp, res)

#２分探索
li, ri = bisect.bisect_left(p_ac, l[i]-1), bisect.bisect_right(p_ac, r[i]-1)    

#ソート関数
org_list = [3, 1, 4, 5, 2]
new_list = sorted(org_list)
print(org_list)
print(new_list)
# [3, 1, 4, 5, 2]
# [1, 2, 3, 4, 5]

#Distance Transformation
    for h in range(0,H):
        for w in range(0,W):
            if h == 0 and w == 0:
                pass
            elif h == 0:
                D[H-h-1][W-w-1]= min(D[H-h-1][W-w-1], D[H-h-1][W-w]+1)
            elif w == 0:   
                D[H-h-1][W-w-1]= min(D[H-h-1][W-w-1], D[H-h][W-w-1]+1)
            else:
                D[H-h-1][W-w-1]= min(D[H-h-1][W-w-1], D[H-h][W-w-1]+1, D[H-h-1][W-w]+1, D[H-h][W-w]+2)
            d_max = max(D[H-h-1][W-w-1], d_max)

"""

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 = list(map(int, input().split()))
X = [0]*M
Y = [0]*M
Z = [0]*M

for m in range(M):
    X[m], Y[m], Z[m] = map(int, input().split())


def main(): 
    uf = UnionFind(N)
    for m in range(M):
        uf.union(X[m]-1, Y[m]-1)
    num = set()
    for n in range(N):
        num.add(uf.find(n))        
        
    print(len(num))
                
                
if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
import sys


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

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

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

    return len(root)


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

Submission status: Accepted

Solution code:
n, m = map(int, input().split())
parent = [i for i in range(n + 1)]
rank = [0] * (n + 1)
s = set()

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

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

for i in range(m):
    x, y, z = map(int, input().split())
    union(x, y)
for i in range(1, n + 1):
    s.add(find(i))
print(len(s))

Submission status: Accepted

Solution code:
n,m = (int(i) for i in input().split())
par,rank,q = [i for i in range(n+1)],[0 for i in range(n+1)],set()
def root(x):
	if par[x]!=x: par[x] = root(par[x])
	return par[x]
def unite(x,y):
	x2,y2 = root(x),root(y)
	if x2!=y2:
		if rank[x2]<rank[y2]: par[x2] = y2
		else: par[y2] = x2
		if rank[x2]==rank[y2]: rank[x2]+=1
for i in range(m):
    x,y,z = (int(i) for i in input().split())
    unite(x,y)
for i in range(1,n+1): q.add(root(i))
print(len(q))

Submission status: Accepted

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

parent = [-1] * (N + 1)

def root(x):
	while parent[x] >= 0:
		x = parent[x]
	return x

def unite(x,y):
	root_x = root(x)
	root_y = root(y)

	if root_x != root_y :
		if parent[root_x] > parent[root_y] :
			parent[root_x]=root_y
		else :
			if parent[root_x] == parent[root_y] :
				parent[root_x] -= 1
			parent[root_y] = root_x
    
	return

for _ in range(M) :
	X, Y, Z = map(int, input().split())
	unite(X, Y)
	
print(sum(i < 0 for i in parent) - 1)

Submission status: Accepted

Solution code:
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n)]
        self.rank = [0 for _ in range(n)]
        
    def find_root(self, x):
        if self.par[x] == x:
            return x
        self.par[x] = self.find_root(self.par[x])
        return self.par[x]
    
    def union(self, x, y):
        x_root = self.find_root(x)
        y_root = self.find_root(y)
        if x_root != y_root:
            if self.rank[x_root] < self.rank[y_root]:
                x_root, y_root = y_root, x_root
            if self.rank[x_root] == self.rank[y_root]:
                self.rank[x_root] += 1
            self.par[y_root] = x_root
            
    def is_same(self, x, y):
        x_root = self.find_root(x)
        y_root = self.find_root(y)
        return x_root == y_root
        
N, M = map(int, input().split())
X = [ list(map(int, input().split())) for _ in range(M)]

uf = UnionFind(N)
for x in X:
    uf.union(x[0]-1, x[1]-1)
    
roots = [ uf.find_root(i) for i in range(N)]
print(len(set(roots)))

Submission status: Accepted

Solution code:
class Node:
    def __init__(self, val):
        self.num = val
        self.val = val
        self.is_parent = True
        self.parent = None
        self.childs = []

    def show(self):
        print(self.num, end=" ")
        print(self.is_parent, end=" ")
        for child in self.childs:
            print(child.num, end=" ")

def root(node):
    depth = 0
    while node.parent != None:
        node = node.parent
        depth += 1
    return node, depth

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

roots = [Node(i) for i in range(N)]
count = N

for i in range(M):
    x, y, z = map(int, input().split())
    x = roots[x-1]
    y = roots[y-1]
    if x.is_parent and y.is_parent:
            y.is_parent = False
            y.parent = x
            count -= 1
            x.childs.append(y)
    else:
        root_x, depth_x = root(x)
        root_y, depth_y = root(y)
        if root_x != root_y:
            if depth_x >= depth_y:
                root_y.is_parent = False
                root_y.parent = root_x
                count -= 1
                root_x.childs.append(root_y)
            else:
                root_x.is_parent = False
                root_x.parent = root_y
                count -= 1
                root_y.childs.append(root_x)

print(count)

Submission status: Accepted

Solution code:
import collections

n,m=list(map(int,input().split()))
#チェックしたか
checked=[False]*n
way=[[] for i in range(n)]
for i in range(m):
  x,y,z=list(map(int,input().split()))
  x-=1
  y-=1
  way[x].append(y)
  way[y].append(x)
ans=0

for i in range(n):
  if checked[i]==False:
    #木に繋がっているノードをチェック済にする
    q=collections.deque()
    q.append(i)
    while len(q)>0:
      c=q.popleft()
      for i in way[c]:
        if not checked[i]:
          checked[i]=True
          q.append(i)
    ans+=1
print(ans)

Submission status: Accepted

Solution code:
n, m = [int(item) for item in input().split()]
xyz = [[int(item) for item in input().split()] for _ in range(m)]

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
    
    def same_check(self, x, y):
        return self.find(x) == self.find(y)

UF = UnionFind(n)
for x, y, z in xyz:
    x -= 1
    y -= 1
    if not UF.same_check(x, y):
        UF.union(x, y)

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

Submission status: Accepted

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

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

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

    def unite(self, x, y):
        rx = self.root(x)
        ry = self.root(y)
        if rx == ry:
            return
        self.par[ry] = rx

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


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

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

m = {i: -1 for i in range(N)}
ans = 0

for i in range(N):
    if m[rf.root(i)] == -1:
        m[rf.root(i)] = 1
        ans += 1

print(ans)

Submission status: Accepted

Solution code:
n, m = map(int, input().split())

p = list(range(n))


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


def union(x, y):
    x, y = find(x), find(y)
    p[x] = p[y] = min(x, y)


for _ in range(m):
    x, y, z = [int(i) - 1 for i in input().split()]
    if find(x) != find(y):
        union(x, y)

ans = set()
for i in range(n):
    find(i)
print(len(set(p)))

Submission status: Accepted

Solution code:
n,m = map(int,input().split())
graph = [[] for i in range(n)]
for i in range(m):
    x,y,z = map(int,input().split())
    graph[x-1].append(y-1)
    graph[y-1].append(x-1)
check = [True]*n
count = 0
for i in range(n):
    if check[i]:
        count += 1
        stack = []
        stack.append(i)
        check[i] = False
        while stack:
            p = stack.pop()
            for j in graph[p]:
                if check[j]:
                    stack.append(j)
                    check[j] = False
    else:
        continue

print(count)

Submission status: Accepted

Solution code:
from scipy.sparse import*
n,m,*t=map(int,open(0).read().split())
print(csgraph.connected_components(csr_matrix(([1]*m,(t[::3],t[1::3])),[n+1]*2))[0]-1)

Submission status: Accepted

Solution code:
from scipy.sparse import*;n,m,*t=map(int,open(0).read().split());print(csgraph.connected_components(csr_matrix(([1]*m,(t[::3],t[1::3])),[n+1]*2))[0]-1)

Submission status: Accepted

Solution code:
from scipy.sparse import*;n,m,*t=map(int,open(0).read().split());t=[i-1for i in t];print(csgraph.connected_components(csr_matrix(([1]*m,(t[::3],t[1::3])),[n]*2))[0])

Submission status: Accepted

Solution code:
class UnionFindTree:
    _node_num = 0
    _parent_list = []
    _tree_len = []
    _num_trees = 0

    def __init__(self, node_num):
        self._node_num = node_num
        self._parent_list = [-1 for i in range(node_num+1)]
        self._tree_len = [0 for i in range(node_num+1)]
        self._num_trees = node_num

    def _root(self, node):
        root = node
        while self._parent_list[root] != -1:
            root = self._parent_list[root]
        return root

    def union(self, x, y):
        xr = self._root(x)
        yr = self._root(y)
        if xr == yr:
            return
        if self._tree_len[xr] < self._tree_len[yr]:
            self._parent_list[xr] = yr
            self._tree_len[yr] += 1
        else:
            self._parent_list[yr] = xr
            self._tree_len[xr] += 1
        self._num_trees -= 1

    def get_num_trees(self):
        return self._num_trees

def main():
    N, M = map(int, input().split())

    uft = UnionFindTree(N)
    for i in range(M):
        x, y, z = map(int, input().split())
        uft.union(x, y)
    print(uft.get_num_trees())

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
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)
for _ in range(M):
    x, y, z = map(int, input().split())
    x -= 1
    y -= 1
    uf.unite(x, y)
print(sum(1 for i in range(N) if uf.root(i)))

Submission status: Accepted

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

Submission status: Accepted

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

Submission status: Accepted

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

Submission status: Accepted

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

Submission status: Accepted

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

Submission status: Accepted

Solution code:
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(visited)
print(ans)

Submission status: Accepted

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

Submission status: Accepted

Solution code:
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

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

Submission status: Accepted

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

Submission status: Accepted

Solution code:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

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): #2つの頂点が同じグループであるかを判定する
        return self.find(x)==self.find(y)

    def unite(self, x, y): #辺で接続されている2つの頂点を投げて統合する
        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)

Submission status: Accepted

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

Submission status: Accepted

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

Submission status: Accepted

Solution code:
#!/usr/bin/env python3

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

Submission status: Accepted

Solution code:
#!/usr/bin/env python3
import sys

class UnionFind:
    def __init__(self, n):
        # par = Parent Number or NoV
        self.par = [-1 for i in range(n+1)]
        # rank = Tree Height
        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
        
        # xのサイズを更新
        self.par[x] += self.par[y]
        # yのサイズ(おやばんごう)をxに
        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


# Generated by 1.1.4 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    M = int(next(tokens))  # type: int
    X = [int()] * (M)  # type: "List[int]" 
    Y = [int()] * (M)  # type: "List[int]" 
    Z = [int()] * (M)  # type: "List[int]" 
    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()

Submission status: Accepted

Solution code:
#!/usr/bin/env python3
import sys

class UnionFind:
    def __init__(self, n):
        # par = Parent Number or NoV
        self.par = [-1 for i in range(n+1)]
        # rank = Tree Height
        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
        
        # xのサイズを更新
        self.par[x] += self.par[y]
        # yのサイズ(おやばんごう)をxに
        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


# Generated by 1.1.4 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    M = int(next(tokens))  # type: int
    X = [int()] * (M)  # type: "List[int]" 
    Y = [int()] * (M)  # type: "List[int]" 
    Z = [int()] * (M)  # type: "List[int]" 
    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()

Submission status: Accepted

Solution code:
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())

Submission status: Accepted

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