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.n = n
        
        
        self.root = [-1]*(n+1)
        
        self.rnk = [0]*(n+1)
        
        self.par = [0]*(n+1)

    
    def Find_Root(self, x):
        if(self.root[x] < 0):
            return x
        else:
            
            self.root[x] = self.Find_Root(self.root[x])
            
            return self.root[x]
    
    def Unite(self, x, y):
        tmpx,tmpy=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.par[tmpy]  =tmpx

        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            self.par[tmpx]  = tmpy
            
            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=map(int,input().split())
tree=UnionFind(N)

state=[-1]*(N+1)
for i in range(M):
    x,y,z=map(int,input().split())
    tree.Unite(x,y)

memo=[0]*(N+1)

ans=0
for i in range(1,N+1):
    if memo[tree.Find_Root(i)]==0:
        ans+=1
        memo[tree.Find_Root(i)]+=1

print(ans)

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

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

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

N, M = map(int, input().split())
X, Y, Z = [0] * M, [0] * M, [0] * M
for i in range(M):
	X[i], Y[i], Z[i] = map(int, input().split())

uf = UnionFind(N)

for j in range(M):
	uf.unite(X[j] - 1, Y[j] - 1)

roots = set([])
for k in range(N):
	roots.add(uf.find(k))
print(len(roots))

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


par=[-1 for i in range(n)]

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

def size(a):
    return -par[root(a)]

def connect(a,b):
    a=root(a)
    b=root(b)
    if a==b:
        return False
    if size(a)<size(b):
        a,b=b,a
    par[a]+=par[b]
    par[b]=a
    return True

xyz=[]
for i in range(m):
    a=[int(j) for j in input().split()]
    xyz.append([a[0]-1,a[1]-1,a[2]%2])
    if root(a[0]-1)!=root(a[1]-1):
        connect(a[0]-1,a[1]-1)
ans=0
for i in range(n):
    if par[i]<0:
        ans+=1
print(ans)

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


par=[-1 for i in range(n)]

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

def size(a):
    return -par[root(a)]

def connect(a,b):
    a=root(a)
    b=root(b)
    if a==b:
        return False
    if size(a)<size(b):
        a,b=b,a
    par[a]+=par[b]
    par[b]=a
    return True

xyz=[]
for i in range(m):
    a=[int(j) for j in input().split()]
    xyz.append([a[0]-1,a[1]-1,a[2]%2])
    if root(a[0]-1)!=root(a[1]-1):
        connect(a[0]-1,a[1]-1)
ans=0
for i in range(n):
    ans+=1/size(i)
print(round(ans))

Solution (Python):
n,m=map(int,input().split())
class UnionFind():
  def __init__(self,n):
    self.n=n
    self.root=[-1]*(n)
    self.rnk=[0]*(n)
    
  def Find_Root(self,x):
    if self.root[x]<0:
      return x
    else:
      self.root[x]=self.Find_Root(self.root[x])
      return self.root[x]
  
  def Unite(self,x,y):
    x = self.Find_Root(x)
    y = self.Find_Root(y)
    if x==y:
      return
    elif self.rnk[x] > self.rnk[y]:
      self.root[x]+=self.root[y]
      self.root[y]=x
    else:
      self.root[y]+=self.root[x]
      self.root[x]=y
      if self.rnk[x] == self.rnk[y]:
        self.rnk[y]+=1
        
  def isSameGroup(self,x,y):
    return self.Find_Root(x) == self.Find_Root(y)
  
  def Count(self,x):
    return -self.root[self.Find_Root(x)]


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

cnt=0
for iii in uf.root:
  if iii<0:
    cnt+=1
print(cnt)

Solution (Python):
n,m=map(int,input().split())
class UnionFind():
  def __init__(self,n):
    self.n=n
    self.root=[-1]*(n+1)
    self.rnk=[0]*(n+1)
    
  def Find_Root(self,x):
    if self.root[x]<0:
      return x
    else:
      self.root[x]=self.Find_Root(self.root[x])
      return self.root[x]
  
  def Unite(self,x,y):
    x = self.Find_Root(x)
    y = self.Find_Root(y)
    if x==y:
      return
    elif self.rnk[x] > self.rnk[y]:
      self.root[x]+=self.root[y]
      self.root[y]=x
    else:
      self.root[y]+=self.root[x]
      self.root[x]=y
      if self.rnk[x] == self.rnk[y]:
        self.rnk[y]+=1
        
  def isSameGroup(self,x,y):
    return self.Find_Root(x) == self.Find_Root(y)
  
  def Count(self,x):
    return -self.root[self.Find_Root(x)]


uf=UnionFind(n)
for iii in range(m):
  x,y,z=map(int,input().split())
  uf.Unite(x,y)

cnt=0
for iii in uf.root:
  if iii<0:
    cnt+=1
print(cnt-1)

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.par = [-1]*(n+1)
        self.sizes=[1]*(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:
            return
        d1=self.par[x]
        d2=self.par[y]
        if d1<=d2:
            self.par[y]=x
            self.sizes[x]=self.sizes[x]+self.sizes[y]
            if d1==d2:
                self.par[x]=self.par[x]-1
        else:
            self.par[x]=y
            self.sizes[y]=self.sizes[x]+self.sizes[y]

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

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

    
    def number(self):
        count=0
        for i in self.par[1:]:
            if i<0:
                count=count+1
        return count
        
N,M=map(int,input().split())
U=UnionFind(N)
for i in range(M):
    X,Y,Z=map(int,input().split())
    U.union(X,Y)
print(U.number())

Solution (Python):

class UnionFind(object):
 
    def __init__(self, n):
        self.par = [i for i in range(n)]
        self.rank = [0 for i in range(n)]
        self.size=[1 for i in range(n)]
 
    def find(self, x):
  
        if self.par[x] == x:
            return x
        else:
            self.par[x]=self.find(self.par[x])
            return self.par[x]
        
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x != y:
            if self.rank[x] < self.rank[y]:
                x, y = y, x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            self.par[y] = x
            self.size[x]+=self.size[y]
            
    def same(self, x, y):
        return self.find(x) == self.find(y)
    
    def tree_size(self,x):
        return self.size[self.find(x)]
    
def main():
    n,m = map(int, input().split())
    uf = UnionFind(n)
    for i in range(m):
        x, y, z = map(int, input().split())
        x -= 1
        y -= 1
        if not uf.same(x,y):
            uf.union(x,y)
    res = 0
    for i in range(n):
        if uf.par[i] == i:
            res += 1
    print(res)

if __name__ == '__main__':
    main()

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

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

    def union(self, x, y):
        xRoot = self.find(x)
        yRoot = self.find(y)
        if self.rank[xRoot] > self.rank[yRoot]:
            self.parent[yRoot] = xRoot
        elif self.rank[xRoot] < self.rank[yRoot]:
            self.parent[xRoot] = yRoot
        elif xRoot != yRoot:
            self.parent[yRoot] = xRoot
            self.rank[xRoot] += 1
        

    def num_disjoint_set(self):
        return len(set([self.find(i) for i in range(n)]))


n, m = map(int, input().split())
g = [(map(int, input().split())) for _ in range(m)]

dset = DisjointSet(n)

for x, y, _ in g:
    dset.union(x - 1, y - 1)

print(dset.num_disjoint_set())

Solution (Python):
import sys
mod = 10**9+7
sys.setrecursionlimit(mod)
N,M=map(int, input().split())

adj={i: set() for i in range(1,N+1)}
for i in range(M):
  x,y,z=map(int, input().split())
  adj[x].add(y)
  adj[y].add(x)
V=set()
def dfs(v):
  if v not in V:
    V.add(v)
    for u in adj[v]: dfs(u)
cnt=0
for i in range(1,N+1):
  if i not in V:
    cnt += 1
    dfs(i)
print(cnt)

Solution (Python):
import sys
input = sys.stdin.readline
'''
allinputs = iter(input().splitlines())
input = lambda : next(allinputs)


N, M = map(int,input().split())
q = []
c = [0] * N
A = [[] for i in range(N)]

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

cost = 0
for i in range(N):
	if c[i] == 0:
		cost += 1
		q.append(i)
		while len(q):
			j = q.pop()
			c[j] = 1
			for k in A[j]:
				if c[k] == 0:
					q.append(k)

print(cost)

Solution (Python):


import sys


s2nn = lambda s: [int(c) for c in s.split(' ')]
ss2nn = lambda ss: [int(s) for s in ss]
ss2nnn = lambda ss: [s2nn(s) for s in ss]
i2s = lambda: sys.stdin.readline().rstrip()
i2n = lambda: int(i2s())
i2nn = lambda: s2nn(i2s())
ii2ss = lambda n: [sys.stdin.readline().rstrip() for _ in range(n)]
ii2nn = lambda n: ss2nn(ii2ss(n))
ii2nnn = lambda n: ss2nnn(ii2ss(n))

def main():
    N, M = i2nn()
    XYZ = ii2nnn(M)
    G = [[] for _ in range(N)]
    for x, y, z in XYZ:
        G[x-1].append(y-1)
        G[y-1].append(x-1)
    S = set()
    c = 0
    for i in range(N):
        if i in S:
            continue
        c += 1
        S.add(i)
        q = [i]
        while len(q) > 0:
            j = q.pop()
            for k in G[j]:
                if k in S:
                    continue
                S.add(k)
                q.append(k)
    print(c)

main()

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

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

    
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
            self.size[y] += self.size[x]
        else:
            self.par[y] = x
            self.size[x] += self.size[y]
            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())

bridge = [tuple(map(int, input().split())) for _ in range(M)]

ins = UnionFind(N)

for i in range(M):
    ins.union(bridge[M-1-i][0],bridge[M-1-i][1])

ans = 0

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

print(ans)

Solution (Python):
class UnionFind:
    def __init__(self,n):
        self.parent = [i for i in range(n+1)]
        self.rank = [0 for i in range(n+1)]
    
    def findroot(self,x):
        if x == self.parent[x]:
            return x
        else:
            y = self.parent[x]
            y = self.findroot(self.parent[x])
            return y
    
    def union(self,x,y):
        px = self.findroot(x)
        py = self.findroot(y)
        if px < py:
            self.parent[py] = px
        else:
            self.parent[px] = py

    def same_group_or_not(self,x,y):
        return self.findroot(x) == self.findroot(y)

N,M = map(int,input().split())
un = UnionFind(N)
xyz = [list(map(int,input().split())) for i in range(M)]
for i in range(M):
    un.union(xyz[i][0]-1,xyz[i][1]-1)
ans = 0
for i in range(N):
    if un.findroot(i) == i:
        ans += 1

print(ans)

Solution (Python):
from collections import deque

N, M = map(int, input().split())
adj = {u: [] for u in range(1, N+1)}
for i in range(M):
    X, Y, Z = map(int, input().split())
    adj[X].append(Y)
    adj[Y].append(X)

remain = set(adj.keys())

ncc = 0  
while len(remain) > 0:
    head = remain.pop()
    remain.add(head)  
    queue = deque()
    queue.append(head)
    while len(queue) > 0:
        u = queue.popleft()
        if u not in remain:
            continue
        remain.remove(u)
        queue.extend(adj[u])
    ncc += 1

print(ncc)

Solution (Python):


import collections
import itertools
import operator
class UnionFind:
    def __init__(self, elems=None):
        class KeyDict(dict):
            def __missing__(self, key):
                self[key] = key
                return key

        self.parent = KeyDict()
        self.rank = collections.defaultdict(int)

        if elems is not None:
            for elem in elems:
                _, _ = self.parent[elem], self.rank[elem]

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

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

    def grouper(self):
        roots = [(x, self.find(x_par)) for x, x_par in self.parent.items()]
        root = operator.itemgetter(1)
        for _, group in itertools.groupby(sorted(roots, key=root), root):
            yield [x for x, _ in group]

N,M=map(int,raw_input().split())
uf=UnionFind(range(1,N+1))
for i in range(M):
    x,y,z=map(int,raw_input().split())
    uf.unite(x,y)

from collections import defaultdict
F=set()
for i in range(1,N+1):
    F.add(uf.find(i))
print(len(F))

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


def search(UF,loc):
    if UF[loc] == loc:
        return UF[loc]
    else:
        UF[loc] = search(UF,UF[loc])
        return UF[loc]
    
dic = [0]*(n+1)
A = [0]*(n+1)
UF = [_ for _ in range(n+1)]
for x,y,z in XYZ:
    UF[x] = search(UF,x)
    UF[y] = search(UF,y)
    if UF[x] != UF[y]:
        UF[max(UF[x],UF[y])] = min(UF[x],UF[y])


for i in range(1,n+1):
    temp = search(UF,i)
    dic[temp] = 1
print(sum(dic))

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

xy = [i for i in range(n + 1)]


def root(x):
    i = x
    while i != xy[i]:
        i = xy[i]
    xy[x] = i
    return i


for _ in range(m):
    x, y = map(int, input().split()[:2])
    xy[root(x)] = root(y)

print(sum(i == v for i, v in enumerate(xy)) - 1)

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

xy = [i for i in range(n + 1)]


def root(x):
    i = x
    a = []
    while i != xy[i]:
        i = xy[i]
        a += [i]
    for b in a:
        xy[b] = i
    return i


for _ in range(m):
    x, y = map(int, input().split()[:2])
    xy[root(x)] = root(y)

ans = sum(i == v for i, v in enumerate(xy)) - 1

print(ans)

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

xy = [i for i in range(n + 1)]


def root(x):
    i = x
    while i != xy[i]:
        i = xy[i]
    xy[x] = i
    return i


for _ in range(m):
    x, y = map(int, input().split()[:2])
    rx = root(x)
    ry = root(y)
    if rx < ry:
        xy[rx] = ry
    else:
        xy[ry] = rx

ans = sum(i == v for i, v in enumerate(xy)) - 1

print(ans)

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

xy = [i for i in range(n + 1)]


def root(x):
    i = x
    while i != xy[i]:
        i = xy[i]
    xy[x] = i
    return i


for _ in range(m):
    x, y = map(int, input().split()[:2])
    xy[root(x)] = root(y)

ans = sum(i == v for i, v in enumerate(xy)) - 1

print(ans)

Solution (Python):
def solve(n, m, x, y, z):
    parent = {i: i for i in range(1, n+1)}
    def find(v):
        if v == parent[v]:
            return v
        else:
            return find(parent[v])
    def union(u, v):
        u = find(u)
        v = find(v)
        if u > v:
            u, v = v, u
        parent[v] = u
    for i in range(m):
        union(x[i], y[i])
    return len(set([find(v) for v in parent.keys()]))

n, m = map(int, input().split())
x = [0] * m
y = [0] * m
z = [0] * m
for i in range(m):
    x[i], y[i], z[i] = map(int, input().split())
print(solve(n, m, x, y, z))

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

xy = [i for i in range(n + 1)]


def root(x):
    i = x
    while i != xy[i]:
        i = xy[i]
    xy[x] = i
    return i


for _ in range(m):
    x, y, z = map(int, input().split())
    rx = root(x)
    ry = root(y)
    if rx != ry:
        xy[ry] = rx

ans = -1
for i, v in enumerate(xy):
    if i == v:
        ans += 1

print(ans)

Solution (Python):
N,M = map(int,input().split())
p = [i for i in range(N)]
g = [[i] for i in range(N)]
for _ in range(M):
  x,y,z = map(int,input().split())
  x,y = p[x-1],p[y-1]
  if x==y:
    continue
  if len(g[x])<len(g[y]):
    x,y = y,x
  g[x] += g[y]
  for z in g[y]:
    p[z] = x
print(len(set(p)))

Solution (Python):
N,M = map(int,input().split())
p = [i for i in range(N)]
g = [[i] for i in range(N)]
for _ in range(M):
  x,y,z = map(int,input().split())
  x,y = p[x-1],p[y-1]
  if x==y:
    continue
  if len(g[x])<len(g[y]):
    x,y = y,x
  g[x] += g[y]
  for z in g[y]:
    p[z] = x
  g[y] = []
print(len(set(p)))

Solution (Python):
from collections import deque


def putid(nodes, edges, group_id, start):
    q = deque([start])

    while q:
        cp = q.popleft()
        if not nodes[cp]:
            nodes[cp] = group_id
            if edges[cp]:
                for edge in edges[cp]:
                    q.append(edge)


def main():
    N, M = map(int, input().split())
    edges = [[] for _ in range(N)]
    nodes = [0] * N

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

    ans = 0

    for i in range(N):
        if not nodes[i]:
            ans += 1
            putid(nodes, edges, ans, i)

    print(ans)


if __name__ == '__main__':
    main()

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

    
    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 groupsize(self):
        self.cnt = 0
        for i, x in enumerate(self.par):
            if x == i:
                self.cnt += 1
        return self.cnt
    
    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 = [list(map(int,input().split())) for i in range(M)]
uf = UnionFind(N)

for i in range(M):
    uf.union(A[i][0]-1, A[i][1]-1)

print(uf.groupsize())

Solution (Python):

N, M = map(int, input().split())
X, Y, Z = (
    zip(*(map(int, input().split()) for _ in range(M))) if M else
    ((), (), ())
)



class UnionFindTree:
    def __init__(self, n):
        self.p = [i for i in range(n + 1)]
        self.r = [0 for _ in range(n + 1)]

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

    def union(self, x, y):
        px = self.find(x)
        py = self.find(y)
        if px != py:
            if self.r[px] < self.r[py]:
                self.p[px] = py
            else:
                self.p[py] = px
                if self.r[px] == self.r[py]:
                    self.r[px] += 1

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


uft = UnionFindTree(N)
for x, y in zip(X, Y):
    uft.union(x, y)
ans = len({uft.find(i) for i in range(1, N + 1)})


print(ans)

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

class UnionFind():
    def __init__(self,size):
        self.table = [-1 for _ in range(size)]
    def find(self,x):
        if self.table[x] < 0:
            return x
        else:
            self.table[x] = self.find(self.table[x])
            return self.table[x]
    def union(self,a,b):
        a1 = self.find(a)
        a2 = self.find(b)
        if a1!= a2:
            if self.table[a1] < self.table[a2]:
                self.table[a1] = a2
            elif self.table[a2] < self.table[a1]:
                self.table[a2] = a1
            else:
                self.table[a1] = a2
                self.table[a2] -= 1
        return
N, M =map(int,input().split())
uf = UnionFind(N)
for _ in range(M):
    x,y,z = map(int,input().split())
    uf.union(x-1,y-1)
cnt = 0
for i in range(N):
    if uf.table[i] < 0:
        cnt += 1
print(cnt)

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

def get_par(x):
  if x == par_list[x]:
    return x
  else:
    par_list[x] = get_par(par_list[x])
    return par_list[x]

N,M=map(int,input().split())
par_list = list(range(N))
for i in range(M):
  Xi,Yi,Zi=map(int,input().split())
  par_Xi = get_par(Xi-1)
  par_Yi = get_par(Yi-1)
  if par_Xi != par_Yi:
    par_list[par_Yi] = par_Xi
    
set_uf = set()
for par in par_list:
  set_uf.add(get_par(par))
  
print(len(set_uf))

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())
uftree = UnionFind(N)
for i in range(M):
    X, Y, Z = map(int, input().split())
    uftree.union(X, Y)
dict = {}
for i in range(N):
    if uftree.find(i+1) not in dict:
        dict[uftree.find(i+1)] = 0

print(len(dict))

Solution (Python):

import copy
import random
import bisect 
import fractions 
import math

import copy
import random
import bisect 
import fractions 
import math
import sys

mod = 10**9+7
sys.setrecursionlimit(mod) 


N,M = map(int,input().split())
tree = [[] for i in range(N)]
for i in range(M):
    X,Y,Z = map(int,input().split())
    X -= 1
    Y -= 1
    tree[X] += [Y]
    tree[Y] += [X]


used = [0 for i in range(N)]

def dfs(node,p):
    used[node] = 1
    
    for new in tree[node]:
        if new == p or used[new] == 1:continue
        dfs(new,node)

cnt = 0
while sum(used) < len(used):
    for i in range(N):
        if used[i] == 0:
            dfs(i,-1)
            cnt += 1

ans = cnt
print(ans)

Solution (Python):

import copy
import random
import bisect 
import fractions 
import math

import copy
import random
import bisect 
import fractions 
import math
import sys

mod = 10**9+7
sys.setrecursionlimit(mod) 


N,M = map(int,input().split())
tree = [[] for i in range(N)]
for i in range(M):
    X,Y,Z = map(int,input().split())
    X -= 1
    Y -= 1
    tree[X] += [Y]
    tree[Y] += [X]


used = [0 for i in range(N)]

def dfs(node,p):
    used[node] = 1
    
    for new in tree[node]:
        if new == p or used[new] == 1:continue
        dfs(new,node)

cnt = 0
while sum(used) < len(used):
    for i in range(N):
        if used[i] == 0:
            dfs(i,-1)
            cnt += 1

ans = N - (sum(used) - cnt)
print(ans)

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

    
    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 groupsize(self):
        self.cnt = 0
        for i,x in enumerate(self.par):
            if x == i:
                self.cnt += 1
        return self.cnt

    
    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())
XYZ = [list(map(int,input().split())) for _ in range(M)]
uf = UnionFind(N)
for i in range(M):
    uf.union(XYZ[i][0]-1,XYZ[i][1]-1)

print(uf.groupsize())

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

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

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

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

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

ans = N
uf = UnionFind(N)
for i in range(M):
    X, Y, _ = map(int, input().split())
    if not uf.is_same(X-1, Y-1):
        uf.union(X-1, Y-1)
        ans -= 1

print(ans)

Solution (Python):
class Node:
    def __init__(self):
        self.is_parent = True
        self.parent = None

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() 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
    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
            else:
                root_x.is_parent = False
                root_x.parent = root_y
                count -= 1

print(count)

Solution (Python):
class Node:
    def __init__(self, val):
        self.num = val
        self.val = val
        self.is_parent = True
        self.parent = None

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
    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
            else:
                root_x.is_parent = False
                root_x.parent = root_y
                count -= 1

print(count)

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

class MergeFind:
    def __init__(self, N):
        self.par = list(range(N))
        self.num_sets = 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
        else:
            self.par[rx] = ry
            self.num_sets -= 1

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

    def get_num_sets(self):
        return self.num_sets

def solve3():
    N, M = [int(_) for _ in raw_input().split()]
    Tree = MergeFind(N)
    for i in range(M):
        Xi, Yi, Zi = [int(_) for _ in raw_input().split()]
        Xi -= 1
        Yi -= 1
        Tree.unite(Xi, Yi)
    print Tree.get_num_sets()

if __name__ == '__main__':
    solve3()

Solution (Python):

import sys
sys.setrecursionlimit(10**6)

class UnionFind:
    def __init__(self, N):
        self.par = list(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
        else:
            self.par[rx] = ry

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

def solve2():
    N, M = [int(_) for _ in raw_input().split()]
    Tree = UnionFind(N)
    for i in range(M):
        Xi, Yi, Zi = [int(_) for _ in raw_input().split()]
        Xi -= 1
        Yi -= 1
        Tree.unite(Xi, Yi)
    UnionSet = set()
    for i in range(N):
        UnionSet.add(Tree.root(i))
    print len(UnionSet)

if __name__ == '__main__':
    solve2()