class UnionFind(): #集合の取り扱い、辺に重み、階層を意識するときは使えない
    def __init__(self,n):
        self.n=n
        self.par = [-1]*n
    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) #x,yの親
        y=self.find(y)

        if x==y: #親が同じなら何もしない
            return 
        if self.par[x]>self.par[y]: #要素数が大きい方をxにする
            x,y=y,x
        self.par[x]+=self.par[y] #xがある集合にyが入った集合をくっつける
        self.par[y]=x

    def size(self,x):
        return -self.par[self.find(x)] #親のサイズ
    
    def same(self,x,y): #親が同じ、すなわち同じ集合か
        return self.find(x)==self.find(y)

    def member(self,x): #同じ木（集合）にある要素全部リストで返す
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i)==root ]
    
    def roots(self): #集合の根になってる要素をリストで返す
        return [i for i , x in enumerate(self.par) if x<0]
    
    def group_count(self): #集合の数、木の数
        return len(self.roots())

    def all_member(self): #辞書型で返す
        return {r: self.member(r) for r in self.roots()}
    def __str__(self):
        return "\n".join('{}:{}'.format(r,self.member(r)) for r in self.roots)
n,m=map(int,input().split())
xyz = [list(map(int, input().split())) for _ in range(m)]
x, y ,z= [list(i) for i in zip(*xyz)]
uf = UnionFind(n)
for i in range(m):
    uf.union(x[i]-1,y[i]-1)
print(uf.group_count()) class UnionFind(): #集合の取り扱い、辺に重み、階層を意識するときは使えない
    def __init__(self,n):
        self.n=n
        self.par = [-1]*n
    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) #x,yの親
        y=self.find(y)

        if x==y: #親が同じなら何もしない
            return 
        if self.par[x]>self.par[y]: #要素数が大きい方をxにする
            x,y=y,x
        self.par[x]+=self.par[y] #xがある集合にyが入った集合をくっつける
        self.par[y]=x

    def size(self,x):
        return -self.par[self.find(x)] #親のサイズ
    
    def same(self,x,y): #親が同じ、すなわち同じ集合か
        return self.find(x)==self.find(y)

    def member(self,x): #同じ木（集合）にある要素全部リストで返す
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i)==root ]
    
    def roots(self): #集合の根になってる要素をリストで返す
        return [i for i , x in enumerate(self.par) if x<0]
    
    def group_count(self): #集合の数、木の数
        return len(self.roots())

    def all_member(self): #辞書型で返す
        return {r: self.member(r) for r in self.roots()}
    def __str__(self):
        return "\n".join('{}:{}'.format(r,self.member(r)) for r in self.roots) UnionFind def __init__(self,n):
        self.n=n
        self.par = [-1]*n
     __init__ self.n=n self.n self n n self.par = [-1]*n self.par self par [-1]*n [-1] -1 n self self n n def find(self,x):
        if self.par[x] <0: #負なら親、要素数
            return x
        else: #正なら親の番号
            self.par[x]=self.find(self.par[x]) #一回調べたら根を繋ぎ変える、経路圧縮
            return self.par[x]
     find if self.par[x] <0: #負なら親、要素数
            return x
        else: #正なら親の番号
            self.par[x]=self.find(self.par[x]) #一回調べたら根を繋ぎ変える、経路圧縮
            return self.par[x]
     self.par[x] <0 self.par[x] self.par self par x 0 return x x self.par[x]=self.find(self.par[x]) self.par[x] self.par self par x self.find(self.par[x]) self.find self find self.par[x] self.par self par x return self.par[x] self.par[x] self.par self par x self self x x def union(self,x,y):
        x=self.find(x) #x,yの親
        y=self.find(y)

        if x==y: #親が同じなら何もしない
            return 
        if self.par[x]>self.par[y]: #要素数が大きい方をxにする
            x,y=y,x
        self.par[x]+=self.par[y] #xがある集合にyが入った集合をくっつける
        self.par[y]=x

     union x=self.find(x) x self.find(x) self.find self find x y=self.find(y) y self.find(y) self.find self find y if x==y: #親が同じなら何もしない
            return 
         x==y x y return if self.par[x]>self.par[y]: #要素数が大きい方をxにする
            x,y=y,x
         self.par[x]>self.par[y] self.par[x] self.par self par x self.par[y] self.par self par y x,y=y,x x y y x self.par[x]+=self.par[y] self.par[x] self.par self par x self.par[y] self.par self par y self.par[y]=x self.par[y] self.par self par y x self self x x y y def size(self,x):
        return -self.par[self.find(x)] #親のサイズ
    
     size return -self.par[self.find(x)] -self.par[self.find(x)] self.par[self.find(x)] self.par self par self.find(x) self.find self find x self self x x def same(self,x,y): #親が同じ、すなわち同じ集合か
        return self.find(x)==self.find(y)

     same return self.find(x)==self.find(y) self.find(x)==self.find(y) self.find(x) self.find self find x self.find(y) self.find self find y self self x x y y def member(self,x): #同じ木（集合）にある要素全部リストで返す
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i)==root ]
    
     member root = self.find(x) root self.find(x) self.find self find x i for i in range(self.n) if self.find(i)==root for i in range(self.n) if self.find(i)==root i range(self.n) range self.n self n self.find(i)==root self.find(i) self.find self find i root if self.find(i)==root i return [i for i in range(self.n) if self.find(i)==root ] [i for i in range(self.n) if self.find(i)==root ] self self x x def roots(self): #集合の根になってる要素をリストで返す
        return [i for i , x in enumerate(self.par) if x<0]
    
     roots i for i , x in enumerate(self.par) if x<0 for i , x in enumerate(self.par) if x<0 i x enumerate(self.par) enumerate self.par self par x<0 x 0 if x<0 i return [i for i , x in enumerate(self.par) if x<0] [i for i , x in enumerate(self.par) if x<0] self self def group_count(self): #集合の数、木の数
        return len(self.roots())

     group_count return len(self.roots()) len(self.roots()) len self.roots() self.roots self roots self self def all_member(self): #辞書型で返す
        return {r: self.member(r) for r in self.roots()}
     all_member r: self.member(r) for r in self.roots() for r in self.roots() r self.roots() self.roots self roots for r in self.roots() r self.member(r) self.member self member r return {r: self.member(r) for r in self.roots()} {r: self.member(r) for r in self.roots()} self self def __str__(self):
        return "\n".join('{}:{}'.format(r,self.member(r)) for r in self.roots) __str__ return "\n".join('{}:{}'.format(r,self.member(r)) for r in self.roots) "\n".join('{}:{}'.format(r,self.member(r)) for r in self.roots) "\n".join "\n" join '{}:{}'.format(r,self.member(r)) '{}:{}'.format '{}:{}' format r self.member(r) self.member self member r self self n,m=map(int,input().split()) n map(int,input().split()) map int input().split() ().split () input split m list(map(int, input().split())) for _ in range(m) for _ in range(m) _ range(m) range m for _ in range(m) list(map(int, input().split())) list map(int, input().split()) map int input().split() ().split () input split xyz = [list(map(int, input().split())) for _ in range(m)] xyz [list(map(int, input().split())) for _ in range(m)] list(i) for i in zip(*xyz) for i in zip(*xyz) i zip(*xyz) zip *xyz xyz for i in zip(*xyz) list(i) list i x, y ,z= [list(i) for i in zip(*xyz)] x [list(i) for i in zip(*xyz)] y z uf = UnionFind(n) uf UnionFind(n) UnionFind n for i in range(m):
    uf.union(x[i]-1,y[i]-1) i range(m) range m uf.union(x[i]-1,y[i]-1) uf.union uf union x[i]-1 x[i] x i 1 y[i]-1 y[i] y i 1 print(uf.group_count()) print uf.group_count() uf.group_count uf group_count z= [list(i) for i in zip(*xyz)] [list(i) for i in zip(*xyz)] z m=map(int,input().split()) map(int,input().split()) m class UnionFind(): #集合の取り扱い、辺に重み、階層を意識するときは使えない
    def __init__(self,n):
        self.n=n
        self.par = [-1]*n
    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) #x,yの親
        y=self.find(y)

        if x==y: #親が同じなら何もしない
            return 
        if self.par[x]>self.par[y]: #要素数が大きい方をxにする
            x,y=y,x
        self.par[x]+=self.par[y] #xがある集合にyが入った集合をくっつける
        self.par[y]=x

    def size(self,x):
        return -self.par[self.find(x)] #親のサイズ
    
    def same(self,x,y): #親が同じ、すなわち同じ集合か
        return self.find(x)==self.find(y)

    def member(self,x): #同じ木（集合）にある要素全部リストで返す
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i)==root ]
    
    def roots(self): #集合の根になってる要素をリストで返す
        return [i for i , x in enumerate(self.par) if x<0]
    
    def group_count(self): #集合の数、木の数
        return len(self.roots())

    def all_member(self): #辞書型で返す
        return {r: self.member(r) for r in self.roots()}
    def __str__(self):
        return "\n".join('{}:{}'.format(r,self.member(r)) for r in self.roots) class UnionFind(): #集合の取り扱い、辺に重み、階層を意識するときは使えない
    def __init__(self,n):
        self.n=n
        self.par = [-1]*n
    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) #x,yの親
        y=self.find(y)

        if x==y: #親が同じなら何もしない
            return 
        if self.par[x]>self.par[y]: #要素数が大きい方をxにする
            x,y=y,x
        self.par[x]+=self.par[y] #xがある集合にyが入った集合をくっつける
        self.par[y]=x

    def size(self,x):
        return -self.par[self.find(x)] #親のサイズ
    
    def same(self,x,y): #親が同じ、すなわち同じ集合か
        return self.find(x)==self.find(y)

    def member(self,x): #同じ木（集合）にある要素全部リストで返す
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i)==root ]
    
    def roots(self): #集合の根になってる要素をリストで返す
        return [i for i , x in enumerate(self.par) if x<0]
    
    def group_count(self): #集合の数、木の数
        return len(self.roots())

    def all_member(self): #辞書型で返す
        return {r: self.member(r) for r in self.roots()}
    def __str__(self):
        return "\n".join('{}:{}'.format(r,self.member(r)) for r in self.roots) UnionFind n,m=map(int,input().split()) map(int,input().split()) n y ,z= [list(i) for i in zip(*xyz)] [list(i) for i in zip(*xyz)] y x, y ,z= [list(i) for i in zip(*xyz)] [list(i) for i in zip(*xyz)] x xyz = [list(map(int, input().split())) for _ in range(m)] [list(map(int, input().split())) for _ in range(m)] xyz uf = UnionFind(n) UnionFind(n) uf
class UnionFind(): #集合の取り扱い、辺に重み、階層を意識するときは使えない
    def __init__(self,n):
        self.n=n
        self.par = [-1]*n
    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) #x,yの親
        y=self.find(y)

        if x==y: #親が同じなら何もしない
            return 
        if self.par[x]>self.par[y]: #要素数が大きい方をxにする
            x,y=y,x
        self.par[x]+=self.par[y] #xがある集合にyが入った集合をくっつける
        self.par[y]=x

    def size(self,x):
        return -self.par[self.find(x)] #親のサイズ
    
    def same(self,x,y): #親が同じ、すなわち同じ集合か
        return self.find(x)==self.find(y)

    def member(self,x): #同じ木（集合）にある要素全部リストで返す
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i)==root ]
    
    def roots(self): #集合の根になってる要素をリストで返す
        return [i for i , x in enumerate(self.par) if x<0]
    
    def group_count(self): #集合の数、木の数
        return len(self.roots())

    def all_member(self): #辞書型で返す
        return {r: self.member(r) for r in self.roots()}
    def __str__(self):
        return "\n".join('{}:{}'.format(r,self.member(r)) for r in self.roots)
n,m=map(int,input().split())
xyz = [list(map(int, input().split())) for _ in range(m)]
x, y ,z= [list(i) for i in zip(*xyz)]
uf = UnionFind(n)
for i in range(m):
    uf.union(x[i]-1,y[i]-1)
print(uf.group_count())