#include<bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
#define int long long
#define endl "\n"
#define Endl "\n"
#define tests int t1234;cin>>t1234;for(int i1234=1;i1234<=t1234;i1234++)
#define ll long long
#define fastio ios_base::sync_with_stdio(false);cin.tie(nullptr);std::cout << std::fixed;std::cout << setprecision(20);
#define takearr(a,n) ll a[n];for(ll i=0;i<n;i++)cin>>a[i]
#define pii pair<int,int>
#define F first
#define S second
#define rep(i,n) for( int i=0;i<(int)n;i++)
#define f(i,a,b) for( int i=(int)a;i<=(int)b;i++)
#define mods ((1000000007))
#define init1d(arr,n,val) for(int i=0;i<n;i++)arr[i]=val;
#define init2d(arr,x,y,val) for(int i=0;i<x;i++)for(int j=0;j<y;j++)arr[i][j]=val;
#define pb push_back
#define mass(vec) (int)vec.size()
#define lb(vec,n,val) ((int)(lower_bound(vec,vec+n,val)-vec))
#define ub(arr,n,val) ((int)(upper_bound(arr,arr+n,val)-arr))


typedef tree<int,null_type, less<>, rb_tree_tag,tree_order_statistics_node_update> oset;
//order_of_key   *find_by_order
typedef tree<int,int, less<>, rb_tree_tag,tree_order_statistics_node_update> omap;
#define dbg(...) cerr << "[" << #__VA_ARGS__ << "]: ", cerr << to_string(__VA_ARGS__) << endl<<endl
template <typename T, size_t N> int SIZE(const T (&t)[N]){ return N; } template<typename T> int SIZE(const T &t){ return t.size(); }string to_string(string &s, int x1=0, int x2=1e9){ return '"' + ((x1 < s.size()) ? s.substr(x1, x2-x1+1) : "") + '"'; }string to_string(const char* s) { string tmp(s); return to_string(tmp); } string to_string(bool b) { return (b ? "true" : "false"); } string to_string(char c){ return string({c}); }template<size_t N> string to_string(bitset<N> &b, int x1=0, int x2=1e9){ string t = ((x1 < b.size()) ? (b.to_string()).substr(x1, x2-x1+1) : "");reverse(begin(t), end(t)); return '"' + t + '"'; }template <typename A, typename... C> string to_string(A (&v), int x1=0, int x2=1e9, C... coords);int l_v_l_v_l = 0, t_a_b_s = 0;template <typename A, typename B> string to_string(pair<A, B> &p) { l_v_l_v_l++; string res = "(" + to_string(p.first) + ", " + to_string(p.second) + ")";l_v_l_v_l--; return res; } template <typename A, typename... C> string to_string(A (&v), int x1, int x2, C... coords) { int rnk = rank<A>::value; string tab(t_a_b_s, ' ');string res = ""; bool first = true; if(l_v_l_v_l == 0) res += endl; res += tab + "["; x1 = min(x1, SIZE(v)), x2 = min(x2, SIZE(v)); auto l = begin(v); advance(l, x1);auto r = l; advance(r, (x2-x1) + (x2 < SIZE(v))); for (auto e = l; e != r; e = next(e)) { if (!first) { res += ", "; } first = false; l_v_l_v_l++;if(e != l){ if(rnk > 1) { res += endl; t_a_b_s = l_v_l_v_l; }; } else{ t_a_b_s = 0; } res += to_string(*e, coords...); l_v_l_v_l--; } res += "]";if(l_v_l_v_l == 0) res += endl; return res; }

const int N=100010;
vector<int>vec[N];int vis[N];

void dfs(int x)
{
  vis[x]=1;
  rep(i,mass(vec[x]))
    {
    if(vis[vec[x][i]]==1)continue;
    dfs(vec[x][i]);
    }
}

int32_t main(){
  fastio;
  int n,m;cin>>n>>m;
  unordered_map<int,int>tt;int ans=0;
  while(m--)
    {
      int x,y,z;cin>>x>>y>>z;
      vec[x].pb(y);
      vec[y].pb(x);
    }
  f(i,1,n)
    {
      if(vis[i]==0)
        {
          ans++;dfs(i);
        }
    }
    cout<<ans<<endl;
}

Measured memory_bytes: 9600