// Original C++ solution (slower):
#include<bits/stdc++.h>

#define INF 1e9

#define llINF 1e18

#define MOD 1000000007

#define pb push_back

#define mp make_pair 

#define F first

#define S second

#define ll long long

#define ull unsigned long long

#define vi vector<ll>

#define vvi vector<vi>

#define DBG_N(hoge) cerr<<" "<<(hoge)<<endl;

#define DBG cerr<<"!"<<endl;

#define BITLE(n) (1LL<<((ll)n))

#define BITCNT(n) (__builtin_popcountll(n))

#define SUBS(s,f,t) ((s).substr((f)-1,(t)-(f)+1))

#define ALL(a) (a).begin(),(a).end()

using namespace std;

vi ans(222222);

ll uk[222222];//1 kakutei 2 wakaranai

vvi E(222222);

void dfs(ll now,ll one){

  for(int i=0;i<E[now].size();i++){

    ll to=E[now][i];

    if(uk[to]==1)continue;

    ll nx;

    if(one==1)nx=2;

    else nx=1;

    uk[to]=1;

    ans[to]=one;

    dfs(to,nx);

  }

}

struct UF

{

  vector<int> par; // 親のインデックスを記憶する配列

  vector<int> sz; // サイズを記憶する。

  vector<int> rank;

  // 初期化

  UF(int n):par(n),sz(n),rank(n){

    for(int i = 0; i < n; i++){

      par[i] = i;sz[i] = 1;rank[i] = 0;

    }

  }

  // 親を求める

  int find(int x) {

    if (par[x] == x) return x;

    else return par[x] = find(par[x]);

  }

  // xとyの属する集合を併合

  void merge(int x, int y) {

    x = find(x); y = find(y);

    if (x == y) return;

    if(rank[x] < rank[y]){

      par[x] = y;

      sz[y] += sz[x];

    }

    else{

      par[y] = x;

      sz[x] += sz[y];

      if(rank[x] == rank[y])rank[x]++;

    }

  }

  // xとyが同じ集合ならtrue

  bool same(int x, int y) { return find(x) == find(y); }

  // 素の集合のサイズを求める

  int size(int n){return sz[find(n)];}

};



int main(){

  cin.tie(0);

  ios::sync_with_stdio(false);

  ll n,m;cin>>n>>m;

  UF uni(111111);

  for(int i=0;i<m;i++){

    ll x,y,z;cin>>x>>y>>z;

    if(z%2==0){

      if(uk[x]==1){

	if(ans[x]==1)ans[y]=1;

	else ans[y]=2;

      }else if(uk[y]==1){

	if(ans[y]==1)ans[x]=1;

	else ans[x]=2;

      }else{

	uk[x]=2;

	uk[y]=2;

	E[x].pb(y);

	E[y].pb(x);

	uni.merge(x,y);

      }

    }else{

      if(uk[x]==1){

	if(ans[x]==1)ans[y]=2;

	else ans[y]=1;

      }else if(uk[y]==1){

	if(ans[y]==1)ans[x]=2;

	else ans[x]=1;

      }else{

	uk[x]=2;

	uk[y]=2;

	E[x].pb(y);

	E[y].pb(x);

	uni.merge(x,y);

      }

    }

  }

  ll cnt=0;

  for(int i=1;i<=n;i++){

    if(uk[i]==0){cnt++;uk[i]=1;}

    else if(uk[uni.find(i)]==2){

      cnt++;

      uk[uni.find(i)]=1;

    }

  }

  cout<<cnt<<endl;

  return 0;

}


// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

#define INF 1e9

#define llINF 1e18

#define MOD 1000000007

#define pb push_back

#define mp make_pair 

#define F first

#define S second

#define ll long long

#define vi vector<ll>

#define vvi vector<vi>

#define BITLE(n) (1LL<<((ll)n))

#define SHIFT_LEFT(n) (1LL<<((ll)n))

#define SUBS(s,f,t) ((s).substr((f)-1,(t)-(f)+1))

#define ALL(a) (a).begin(),(a).end()

using namespace std;

struct UF

{

  vector<int> par;

  vector<int> sz;

  vector<int> rank;

  UF(int n):par(n),sz(n),rank(n){

    for(int i = 0; i < n; i++){

      par[i] = i;sz[i] = 1;rank[i] = 0;

    }

  }

  int find(int x) {

    if (par[x] == x) return x;

    else return par[x] = find(par[x]);

  }

  void merge(int x, int y) {

    x = find(x); y = find(y);

    if (x == y) return;

    if(rank[x] < rank[y]){

      par[x] = y;

      sz[y] += sz[x];

    }

    else{

      par[y] = x;

      sz[x] += sz[y];

      if(rank[x] == rank[y])rank[x]++;

    }

  }

  bool same(int x, int y) { return find(x) == find(y); }

  int size(int n){return sz[find(n)];}

};

vi kaku(222222,-1);

int main(){

  cin.tie(0);

  ios::sync_with_stdio(false);

  ll n,m;cin>>n>>m;

  UF uni(n);

  for(int i=0;i<m;i++){

    ll x,y,z;

    cin>>x>>y>>z;

    /*   z%=2;

    if(z == 0){

      

    }else{

    }

    */

    uni.merge(x-1,y-1);

  }

  ll ans = 0;

  for(int i=0;i<n;i++){

    if(uni.find(i) == i)

      ans++;

  }

  cout<<ans<<endl;

  return 0;

}


// Fastest known solution for this problem: