qyliang/CodeNanoFix huggingface dataset:
# Buggy code:
#17:11
n,m = map(int,input().split())
pre = [-1 for i in range(n)]
ans = n
for _ in range(m):
  x,y,z = map(int,input().split())
  x -= 1
  y -= 1
  X = [x]
  Y = [y]
  while pre[x] != -1:
    X.append(x)
    x = pre[x]
  while pre[y] != -1:
    Y.append(y)
    y = pre[y]
  if x != y:
    ans -= 1
    for xx in X:
      pre[xx] = y
    for yy in Y:
      pre[yy] = y
    pre[x] = y
#print(pre)
print(ans)

# Fixed code:
#17:11
n,m = map(int,input().split())
pre = [i for i in range(n)]
ans = n
for _ in range(m):
  x,y,z = map(int,input().split())
  x -= 1
  y -= 1
  X = [x]
  Y = [y]
  while pre[x] != x:
    X.append(x)
    x = pre[x]
  while pre[y] != y:
    Y.append(y)
    y = pre[y]
  if x != y:
    ans -= 1
    for xx in X:
      pre[xx] = y
    for yy in Y:
      pre[yy] = y
    pre[x] = y
#print(pre)
print(ans)
# Buggy code:
class union_find():
    def __init__(self, n):
        self.par = [i for i in range(n + 1)]
        self.rank = [1 for i in range(n + 1)]

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

        ret = self.find(self.par[c])
        self.par[c] = ret
        return ret

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

        if self.rank[yr] > self.rank[xr]:
            self.par[xr] = yr
        else:
            self.par[yr] = xr
            if self.rank[xr] == self.rank[yr]:
                self.rank[xr] += 1

    def show(self):
        print('parent', self.par[1:])
        print('rank', self.rank[1:])

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

for i in range(M):
    x, y, z = map(int, input().split())
    uf.union(x, y)


print([i == v for i, v in enumerate(uf.par[1:])].count(True))






# Fixed code:
class union_find():
    def __init__(self, n):
        self.par = [i for i in range(n + 1)]
        self.rank = [1 for i in range(n + 1)]

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

        ret = self.find(self.par[c])
        self.par[c] = ret
        return ret

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

        if self.rank[yr] > self.rank[xr]:
            self.par[xr] = yr
        else:
            self.par[yr] = xr
            if self.rank[xr] == self.rank[yr]:
                self.rank[xr] += 1

    def show(self):
        print('parent', self.par[1:])
        print('rank', self.rank[1:])

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

for i in range(M):
    x, y, z = map(int, input().split())
    uf.union(x, y)


print([i == v for i, v in enumerate(uf.par)].count(True) - 1)
# Buggy code:
import math
import operator as op
from functools import reduce
from fractions import Fraction as frac

def ncr(n, r):
    r = min(r, n-r)
    numer = reduce(op.mul, range(n, n-r, -1), 1)
    denom = reduce(op.mul, range(1, r+1), 1)
    return numer / denom
def rd(p):
    if(p==0):
        return input()
    if(p==1):
        return int(input())
    if(p==2):
        return map(int,input().split())
    if(p==3):
        return list(map(int,input().split()))
        

# t=rd(1)
def find(u,par):
    if(par[u]<0):
        return u
    else:
        return find(par[u],par)
def uni(x,y,par):
    u=find(x,par)
    v=find(y,par)
    if(par[u]<par[v]):
        par[u]+=par[v]
        par[v]=u
        
    else:
        par[v]+=par[u]
        par[u]=v
t=1
for term in range(1,t+1):
    n,m=rd(2)
    par=[-1 for i in range(n+1)]
    
    
    for i in range(m):
        x,y,z=rd(2)
        uni(x,y,par)
    ans=0
    for i in range(1,n+1):
        if(par[i]<0):
            ans+=1
    print(ans)
        
    
    

# Fixed code:
import math
import operator as op
from functools import reduce
from fractions import Fraction as frac

def ncr(n, r):
    r = min(r, n-r)
    numer = reduce(op.mul, range(n, n-r, -1), 1)
    denom = reduce(op.mul, range(1, r+1), 1)
    return numer / denom
def rd(p):
    if(p==0):
        return input()
    if(p==1):
        return int(input())
    if(p==2):
        return map(int,input().split())
    if(p==3):
        return list(map(int,input().split()))

global par
par=[-1 for i in range(100001)]
# t=rd(1)
def find(u):
    if(par[u]<0):
        return u
    else:
        return find(par[u])
def uni(x,y):
    u=find(x)
    v=find(y)
    if u==v:
        return
    if(par[u]<par[v]):
        par[u]+=par[v]
        par[v]=u
    else:    
        par[v]+=par[u]
        par[u]=v
t=1
for term in range(1,t+1):
    n,m=rd(2)
    for i in range(m):
        x,y,z=rd(2)
        uni(x,y)
        # print(par[1:n+1])
    ans=0
    for i in range(1,n+1):
        if(par[i]<0):
            ans+=1
    
    print(ans)
# Buggy code:
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])

    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


import sys
sys.setrecursionlimit(10000000)
input = sys.stdin.readline

n, m = map(int, input().split())
u = UnionFind(n)
for _ in range(m):
    a, b, c = map(int, input().split())
    a -= 1
    b -= 1
    u.Unite(a, b)
print(len(set(u.Find_Root(i) for i in range(n))))


# Fixed code:
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


import sys
sys.setrecursionlimit(10000000)
input = sys.stdin.readline

n, m = map(int, input().split())
u = UnionFind(n)
for _ in range(m):
    a, b, c = map(int, input().split())
    a -= 1
    b -= 1
    u.Unite(a, b)
print(len(set(u.Find_Root(i) for i in range(n))))
# Buggy code:
n, m = map(int, input().split())
adj = [[] for _ in range(m)]
for _ in range(m):
  x, y, z = map(int, input().split())
  adj[x-1].append(y-1)
  adj[y-1].append(x-1)
opn = [True] * n
count = 0
for i in range(n):
  if opn:
    count += 1
    opn[i] = False
    stack = [i]
    while stack:
      u = stack.pop()
      for v in adj[u]:
        if opn[v]:
          stack.append(v)
          opn[v] = False
print(count)

# Fixed code:
n, m = map(int, input().split())
adj = [[] for _ in range(n)]
for _ in range(m):
  x, y, z = map(int, input().split())
  adj[x-1].append(y-1)
  adj[y-1].append(x-1)
opn = [True] * n
count = 0
for i in range(n):
  if opn[i]:
    count += 1
    opn[i] = False
    stack = [i]
    while stack:
      u = stack.pop()
      for v in adj[u]:
        if opn[v]:
          stack.append(v)
          opn[v] = False
print(count)
# Buggy code:
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n)]
        self.rank = [0] * (n)

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

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

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

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


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

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

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

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

for i in range(m):
  x,y,z=map(int,input().split())
  U.union(x-1,y-1)
ans=0
for i,j in enumerate(U.par):
  if i==j:
    ans+=1
print(ans)
# Buggy code:
import sys
sys.setrecursionlimit(10 ** 6)
def dfs(v):
    global gone
    stack = [v]
    gone[v] = True
    while stack:
        v = stack.pop()
        for w in graph[v]:
            gone[w] = True
            stack.append(w)

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

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

print(ans)

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

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

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

print(ans)
# Buggy code:
class uf_tree():

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

    def indep(self):
        dep =0
        for i in range(self.n):
            if i == self.par[i]:
                dep += 1

        return dep

    def unite(self,child,mas):
        if self.root(child) == self.root(mas):
            return
        else:
            self.par[self.root(child)] = self.root(self.mas)

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

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



n,m = map(int,input().split())
uf = uf_tree(n+1)
for i in range(m):
    x,y,z = map(int,input().split())
    uf.unite(x,y)

print(uf.indep()-1)


# Fixed code:
class uf_tree():

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

    def indep(self):
        dep =0
        for i in range(self.n):
            if i == self.par[i]:
                dep += 1

        return dep

    def unite(self,child,mas):
        if self.root(child) == self.root(mas):
            return
        else:
            self.par[self.root(child)] = self.root(mas)

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

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



n,m = map(int,input().split())
uf = uf_tree(n+1)
for i in range(m):
    x,y,z = map(int,input().split())
    uf.unite(x,y)

print(uf.indep()-1)
# Buggy code:
n,m=map(int,input().split())
    
root=[int(i) for i in range(n)] 
rank=[0]*n    
def find(x):
    if root[x]==x:
        return x 
    else:
        return find(root[x])

for i in range(m):
    x,y,z=map(int,input().split())
    fx=find(x-1)
    fy=find(y-1)
    if rank[fx]>=rank[fy]:
        root[fy]=fx
        if rank[fx]==rank[fy]:
            rank[fx]+=1
    else:
        root[fx]=fy 
a=()
for i in range(n):
    a.add(find(i)) 
print(len(a))

# Fixed code:
n,m=map(int,input().split())
    
root=[int(i) for i in range(n)] 
rank=[0]*n    
def find(x):
    if root[x]==x:
        return x 
    else:
        return find(root[x])

for i in range(m):
    x,y,z=map(int,input().split())
    fx=find(x-1)
    fy=find(y-1)
    if rank[fx]>=rank[fy]:
        root[fy]=fx
        if rank[fx]==rank[fy]:
            rank[fx]+=1
    else:
        root[fx]=fy 
a=[]
for i in range(n):
    a.append(find(i)) 
print(len(set(a)))
# Buggy code:
# input = sys.stdin.readline
from bisect import *
from collections import *
from heapq import *
# import functools
# import itertools
# import math
N,M=map(int,input().split())
XYZ=[list(map(int,input().split())) for i in range(M)]
data=[[] for i in range(N+1)]
ittenai=[]
for x,y,z in XYZ:
    data[x].append(y)
    data[y].append(x)
    ittenai.append(x)
    ittenai.append(y)


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

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


# Fixed code:
# input = sys.stdin.readline
from bisect import *
from collections import *
from heapq import *
# import functools
# import itertools
# import math
N,M=map(int,input().split())
XYZ=[list(map(int,input().split())) for i in range(M)]
data=[[] for i in range(N+1)]
ittenai=[]
for x,y,z in XYZ:
    data[x].append(y)
    data[y].append(x)
    ittenai.append(x)
    ittenai.append(y)


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

    count+=1
    while stack:
        num=stack.popleft()
        for i in data[num]:
            if i in ittenai:
                ittenai.remove(i)
                stack.append(i)
print(count)
# Buggy code:
import sys
from collections import deque
sys.setrecursionlimit(10**9)
input = sys.stdin.readline
n, m = map(int, input().split())
memo = set(list(range(n)))
E = [[] for i in range(n)]
for i in range(m):
    x, y, z = map(int, input().split())
    E[x-1].append(y-1)
    E[y-1].append(x-1)
def dfs(cur, pre):
    stack = deque([[cur, pre]])
    while stack:
        cur, pre = stack.pop()
        memo.discard(cur)
        for e in E[cur]:
            if e != pre and e in memo:
                stack.append([e, cur])
ans = 0
for i in range(n):
    if i in memo:
        dfs(cur, -1)
        ans += 1
print(ans)


# Fixed code:
import sys
from collections import deque
sys.setrecursionlimit(10**9)
input = sys.stdin.readline
n, m = map(int, input().split())
memo = set(list(range(n)))
E = [[] for i in range(n)]
for i in range(m):
    x, y, z = map(int, input().split())
    E[x-1].append(y-1)
    E[y-1].append(x-1)
def dfs(cur, pre):
    stack = deque([[cur, pre]])
    while stack:
        cur, pre = stack.pop()
        if pre != -1:
            memo.discard(cur)
        for e in E[cur]:
            if e != pre and e in memo:
                stack.append([e, cur])
ans = 0
while len(memo):
    cur = memo.pop()
    dfs(cur, -1)
    ans += 1
print(ans)
# Buggy code:
sys.setrecursionlimit(100000)

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

# Fixed code:
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))
# Buggy code:
N,M=map(int,input().split())

flag=list(range(N))
def takeflag(p):
    stock=[]
    while flag[flag[p]]!=flag[p]:
        stock.append(p)
        p=flag[p]
    p=flag[p]
    for i in stock:
        flag[i]=p
    return p

for i in range(M):
    x,y,z = map(int,input().split())
    x,y = map(takeflag,(x,y))
    x,y = min(x,y),max(x,y)
    flag[x]=y

st=set()
for i in range(N):
    st.add(takeflag(i))

print(len(st))

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

flag=list(range(N))
def takeflag(p):
    stock=[]
    while flag[flag[p]]!=flag[p]:
        stock.append(p)
        p=flag[p]
    p=flag[p]
    for i in stock:
        flag[i]=p
    return p

for i in range(M):
    x,y,z = map(int,input().split())
    x,y=x-1,y-1
    x,y = map(takeflag,(x,y))
    x,y = min(x,y),max(x,y)
    flag[x]=y

st=set()
for i in range(N):
    st.add(takeflag(i))

print(len(st))
# Buggy code:
class UnionFind():
    def __init__(self, n):
        self.par = [i for i in range(n)]
        self.rank = [0] * 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 union(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x != 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 samegrp(self, x, y):
        return self.root(x) == self.root(y)

from mymodules.somedatastrs import UnionFind

n, m = [int(x) for x in input().split()]
A = UnionFind(n)
ans = n
for i in range(m):
    x, y, _ = [int(z) - 1 for z in input().split()]
    if not A.samegrp(x, y):
        ans -=1
    A.union(x, y)

print(ans)

# Fixed code:
class UnionFind():
    def __init__(self, n):
        self.par = [i for i in range(n)]
        self.rank = [0] * 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 union(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x != 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 samegrp(self, x, y):
        return self.root(x) == self.root(y)

n, m = [int(x) for x in input().split()]
A = UnionFind(n)
ans = n
for i in range(m):
    x, y, _ = [int(z) - 1 for z in input().split()]
    if not A.samegrp(x, y):
        ans -=1
    A.union(x, y)

print(ans)
# Buggy 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): 
        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)
ans=chk=0
w=collections.deque()
for i in range(m):
    x,y,z=map(int,input().split())
    uf.unite(x,y)
print(uf.group_num)


# Fixed 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):
        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)
ans=chk=0
for i in range(m):
    x,y,z=map(int,input().split())
    uf.unite(x-1,y-1)
print(uf.grp)
# Buggy code:
f-8

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

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

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

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

print(count)

# Fixed code:
# coding: utf-8

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

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

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

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

print(count)
# Buggy code:
a = input().split()
N = int(a[0])
M = int(a[1])

l = []
f = []
for i in range(N):
	temp = []
	l.append(temp)
	f.append(0)

for i in range(M):
	b = input().split()
	X = int(b[0]) - 1
	Y = int(b[1]) - 1
	l[X].append(Y)
	l[Y].append(X)

def search(cnt, li, flag, num):
	if(flag[num] == 0):
		flag[num] = cnt
		if(len(li[num]) != 0):
			for i in range(len(li[num])):
				search(cnt, li, flag, li[num][i])
		
cnt = 0
for i in range(N):
	print(f)
	if(f[i] == 0):
		cnt += 1
		search(cnt, l, f, i)			
print(cnt)

# Fixed code:
import sys
sys.setrecursionlimit(1000000)

a = input().split()
N = int(a[0])
M = int(a[1])

l = []
f = []
for i in range(N):
	temp = []
	l.append(temp)
	f.append(0)

for i in range(M):
	b = input().split()
	X = int(b[0]) - 1
	Y = int(b[1]) - 1
	l[X].append(Y)
	l[Y].append(X)

def search(cnt, li, flag, num):
	if(flag[num] == 0):
		flag[num] = cnt
		if(len(li[num]) != 0):
			for i in range(len(li[num])):
				search(cnt, li, flag, li[num][i])
		
cnt = 0
for i in range(N):
	if(f[i] == 0):
		cnt += 1
		search(cnt, l, f, i)			
print(cnt)