stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

typedef long long int ll;

typedef pair<ll, ll> P;

typedef vector<int> VI;

typedef vector<VI> VVI;

const ll MOD = 1000000007;

const ll INF = 1000000000;

#define REP(i, n) for(int i = 0; i < n; i++)

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



VVI edge(100001, VI(0)); vector<bool> flag(100001, false);

void dfs(int v) {

	flag[v] = true;

	REP(i, edge[v].size()) {

		if (!flag[edge[v][i]])

			dfs(edge[v][i]);

	}

	return;

}



int main() {

	int n, m;

	cin >> n >> m;

	int x, y, z;

	REP(i, m) {

		cin >> x >> y >> z;

		edge[x].push_back(y);

		edge[y].push_back(x);

	}

	int ans = 0;

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

		if (!flag[i]) {

			dfs(i);

			ans++;

		}

	}

	cout << ans;

}

// Faster C++ solution for the same problem (measured speedup: 3.4768684292451977x):
#include <bits/stdc++.h>

using namespace std;

typedef long long int ll;

typedef pair<ll, ll> P;

typedef vector<ll> VI;

typedef vector<VI> VVI;

const ll MOD = 1000000007;

const ll INF = 1e18;

#define REP(i, n) for(int i = 0; i < n; i++)

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



struct unionfind {

	vector<int> par, siz;

	unionfind(int N) : par(N), siz(N,1) {

		for (int i = 0; i < N; i++) par[i] = i;

	}

	int root(int x) {

		while(par[x] != x) x = par[x] = par[par[x]];

		return x;

	}

	void unite(int x, int y) {

		x = root(x); y = root(y);

		if (x == y) return;

		if (siz[x] < siz[y]) swap(x, y);

		siz[x] += siz[y];

		par[y] = x;

	}

	bool same(int x, int y) {

		return root(x) == root(y);

	}

	int size(int x) {

		return siz[root(x)];

	}

};



int main(){

	int n, m; cin >> n >> m;

	unionfind uf(n);

	int x, y, z;

	REP(i,m){

		cin >> x >> y >> z;

		x--; y--;

		uf.unite(x,y);

	}

	vector<bool> f(n,0);

	int ans=0;

	REP(i,n){

		int r=uf.root(i);

		if(!f[r]){

			f[r]=1;

			ans++;

		}

	}

	cout << ans << endl;

	return 0;

}
// Slower C++ solution:
#include<bits/stdc++.h>

 

using namespace std;

 

#define INF 1000000007

#define LINF 1000000000000000007

 

typedef long long i64;

typedef pair<i64,i64> P;





int n,m;

vector<int> v[101010];//v_from(to)

bool used[101010];

bool color[101010];



int main(){

	cin >> n >> m;

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

		int a,b,c;

		cin >> a >> b >> c;

		c %= 2;

		v[a].push_back(b);

		v[b].push_back(a);

	}

	

	int cnt = 0;

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

		if(used[i]) continue;

		cnt++;

		queue<int> q;

		q.push(i);//ばしょ

		while(!q.empty()){

			int p = q.front();

			q.pop();

			used[p] = 1;

			for(int j = 0; j < v[p].size(); j++){

				if(used[v[p][j]]) continue;

				q.push(v[p][j]);

			}

		}

	}

	cout << cnt << endl;

	

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.2182914772022886x):
#include<bits/stdc++.h>



using namespace std;



#define INF 1000000007

#define LINF (1LL << 60)

#define PI 3.14159265358979



typedef long long i64;

typedef pair<i64,i64> P;



inline i64 mod(i64 a, i64 m) { return (a % m + m) % m; }



template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }

template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }







int n, m, a[101001], b[101010], c[101010];

//union-find

struct UnionFind {

	vector<int> par, depth, sz;

	UnionFind(int n) : par(n+1), depth(n+1), sz(n+1){

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

			par[i] = i;

			depth[i] = 0;

			sz[i] = 1;

		}

	}

	int find(int x){

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

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

	}

	void unite(int x, int y){

		x = find(x);

		y = find(y);

		if(x == y) return;

		sz[x] += sz[y];

		sz[y] = sz[x];

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

			par[x] = y;

		}

		else{

			par[y] = x;

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

		}

	}

	bool same(int x, int y){

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

	}

	int size(int x){

		return sz[find(x)];

	}

};

////

void solve(){

	cin >> n >> m;

	UnionFind uf(n);

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

		cin >> a[i] >> b[i] >> c[i];

		a[i]--; b[i]--;

		c[i] %= 2;

		uf.unite(a[i],b[i]);

	}

	

	bool used[101010] = {0};

	int cnt = 0;

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

		if(used[uf.find(i)]) continue;

		used[uf.find(i)] = 1;

		cnt++;

	}

	cout << cnt << endl;

}



int main(){

	std::cin.tie(0);

	std::ios::sync_with_stdio(false);

	int t = 1;

	//cin >> t;

	while(t--){

		solve();

	}

	

	return 0;

}
// Slower C++ solution:
#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < n; i++)

#define rrep(i, n) for (int i = n - 1; i >= 0; i--)

using namespace std;

using Graph = vector<vector<int>>;

#define MOD 1000000007

#define MOD2 998244353

#define INF ((1<<30)-1)

#define LINF (1LL<<60)

#define EPS (1e-10)

typedef long long ll;

typedef pair<ll, ll> P;



ll x[100010];

ll y[100010];

ll z[100010];

vector<int> g[100010];



bool seen[100010];



void dfs(int v){

    seen[v] = true;

    for(auto nv : g[v]){

        if (seen[nv]) continue;

        seen[nv] = true;

        dfs(nv);

    }

}



int main(){

    int n, m;

    cin >> n >> m;

    rep(i, m) cin >> x[i] >> y[i] >> z[i];

    rep(i, m) x[i]--, y[i]--;



    rep(i, m){

        g[x[i]].push_back(y[i]);

        g[y[i]].push_back(x[i]);

    }



    int cnt = 0;



    rep(i, n){

        if (seen[i]) continue;

        dfs(i);

        cnt++;

    }

    cout << cnt << endl;



    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.4887515700907437x):
#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < n; i++)

#define rrep(i, n) for (int i = n - 1; i >= 0; i--)

using namespace std;

using Graph = vector<vector<int>>;

#define MOD 1000000007

#define MOD2 998244353

#define INF ((1<<30)-1)

#define LINF (1LL<<60)

#define EPS (1e-10)

typedef long long ll;

typedef pair<ll, ll> P;



struct UnionFind{

    vector<ll> par;

    vector<ll> sizes;

    UnionFind(ll n) : par(n), sizes(n, 1) {

        rep(i,n) par[i] = i;

    }

    int find(ll x) {

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

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

    }

    void unite(ll x, ll y) {

        x = find(x);

        y = find(y);

        if (x == y) return;

        if (sizes[x] < sizes[y]) swap(x, y);

        par[y] = x;

        sizes[x] += sizes[y];

    }



    bool same(ll x, ll y) {

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

    }



    ll size(ll x) {

        return sizes[find(x)];

    }

};



ll x[100010];

ll y[100010];

ll z[100010];



bool seen[100010];



int main(){

    int n, m;

    cin >> n >> m;

    rep(i, m) cin >> x[i] >> y[i] >> z[i];

    rep(i, m) x[i]--, y[i]--;



    UnionFind tree(n);



    rep(i, m){

        tree.unite(x[i], y[i]);

    }

    map<int,int> rootmp;

    rep(i, n){

        rootmp[tree.find(i)]++;

    }

    cout << rootmp.size() << endl;



    return 0;

}
// Slower C++ solution:
#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < n; i++)

#define rrep(i, n) for (int i = n - 1; i >= 0; i--)

using namespace std;

using Graph = vector<vector<int>>;

#define MOD 1000000007

#define MOD2 998244353

#define INF ((1<<30)-1)

#define LINF (1LL<<60)

#define EPS (1e-10)

typedef long long ll;

typedef pair<ll, ll> P;



ll x[100010];

ll y[100010];

ll z[100010];

vector<int> g[100010];



bool seen[100010];



void dfs(int v){

    seen[v] = true;

    for(auto nv : g[v]){

        if (seen[nv]) continue;

        seen[nv] = true;

        dfs(nv);

    }

}



int main(){

    int n, m;

    cin >> n >> m;

    rep(i, m) cin >> x[i] >> y[i] >> z[i];

    rep(i, m) x[i]--, y[i]--;



    rep(i, m){

        g[x[i]].push_back(y[i]);

        g[y[i]].push_back(x[i]);

    }



    int cnt = 0;



    rep(i, n){

        if (seen[i]) continue;

        dfs(i);

        cnt++;

    }

    cout << cnt << endl;



    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.382784089021574x):
#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < n; i++)

#define rrep(i, n) for (int i = n - 1; i >= 0; i--)

using namespace std;

using Graph = vector<vector<int>>;

#define MOD 1000000007

#define MOD2 998244353

#define INF ((1<<30)-1)

#define LINF (1LL<<60)

#define EPS (1e-10)

typedef long long ll;

typedef pair<ll, ll> P;



struct UnionFind{

    vector<ll> par;

    vector<ll> sizes;

    UnionFind(ll n) : par(n), sizes(n, 1) {

        rep(i,n) par[i] = i;

    }

    int find(ll x) {

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

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

    }

    void unite(ll x, ll y) {

        x = find(x);

        y = find(y);

        if (x == y) return;

        if (sizes[x] < sizes[y]) swap(x, y);

        par[y] = x;

        sizes[x] += sizes[y];

    }



    bool same(ll x, ll y) {

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

    }



    ll size(ll x) {

        return sizes[find(x)];

    }

};



ll x[100010];

ll y[100010];

ll z[100010];



bool seen[100010];



int main(){

    int n, m;

    cin >> n >> m;

    rep(i, m) cin >> x[i] >> y[i] >> z[i];

    rep(i, m) x[i]--, y[i]--;



    UnionFind tree(n);

    int cnt = n;

    rep(i, m){

        if (!tree.same(x[i], y[i])) cnt--;

        tree.unite(x[i], y[i]);

    }



    cout << cnt << endl;



    return 0;

}
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

#define INF (1<<28)

#define DEKAI 1000000007

#define lp(i,n) for(int i=0;i<n;i++)

#define int long long

int ans[100010];



signed main(){

  int n,m;

  cin>>n>>m;

  vector<int> l[100010];

  lp(i,m){

    int a,b,c;

    cin>>a>>b>>c;

    l[a].push_back(b);

    l[b].push_back(a);

  }

  int cnt=0;

  lp(i,n){

    if(ans[i+1]==1) continue;

    cnt++;

    queue<int> q;

    q.push(i+1);

    while(!q.empty()){

      int now=q.front();

      q.pop();

      lp(i,l[now].size()){

        int next=l[now][i];

        if(ans[next]==0){

          ans[next]=1;

          q.push(next);

        }

      }

    }

  }

  cout<<cnt<<endl;

  return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.562329668649454x):
#include<bits/stdc++.h>

using namespace std;

#define INF (1<<28)

#define DEKAI 1000000007

#define lp(i,n) for(int i=0;i<n;i++)

#define int long long

struct UnionFind{

  int n;//要素数

  vector<int> csize;//子の数(include 自分)

  vector<int> parent;//親

  int setnum;//集合の数



  UnionFind();

  UnionFind(int v){

    n=v;

    setnum=v;

    csize.assign(v+1,1);    

    parent.assign(v+1,0);

    iota(parent.begin(),parent.end(),0);

  }

  int find(int x){

    return (x==parent[x]?x:parent[x]=find(parent[x]));

  }

  bool same(int x,int y){

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

  }

  bool unite(int x,int y){

    x=find(x);

    y=find(y);

    if(x==y) return false;

    if(csize[x]<csize[y]) swap(x,y);

    csize[x]+=csize[y];

    parent[y]=x;

    setnum--;

    return true;

  }

  //if already united, return false;

  int size(int x){

    return csize[find(x)];

  }

  int count(){

    return setnum;

  }

};



int a[100000];

signed main(){

  int n,m;

  cin>>n>>m;

  UnionFind UF(n);

  lp(i,m){

    int a,b,c;

    cin>>a>>b>>c;

    UF.unite(a,b);

  }

  cout<<UF.count()<<endl;

  return 0;

}
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;



typedef long long ll;

typedef pair<int,int> P;



#define p_ary(ary,a,b,i) do { cout << "["; for (int (i) = (a);(i) < (b);++(i)) cout << ary[(i)] << ((b)-1 == (i) ? "" : ", "); cout << "]\n"; } while(0)

#define p_map(map,it) do {cout << "{";for (auto (it) = map.begin();;++(it)) {if ((it) == map.end()) {cout << "}\n";break;}else cout << "" << (it)->first << "=>" << (it)->second << ", ";}}while(0)



vector<vector<int>> edges(100000);

vector<int> used(100000,-1);

int c = 0;



void dfs(int i,int p = -1) {

    used[i] = c;

    for (int& j : edges[i]) if (j != p && used[j] < 0) dfs(j,i);

}



int main() {

    int n,m;

    cin >> n >> m;

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

        int u,v,w;

        cin >> u >> v >> w;

        u--;v--;

        edges[u].push_back(v);

        edges[v].push_back(u);

    }

    for (int i = 0;i < n;++i) if (used[i] < 0) {

        c++;

        dfs(i);

    }

    cout << c << endl;

    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.9262367254562687x):
#include<bits/stdc++.h>

using namespace std;



typedef long long ll;

typedef pair<int,int> P;



#define p_ary(ary,a,b) do { cout << "["; for (int count = (a);count < (b);++count) cout << ary[count] << ((b)-1 == count ? "" : ", "); cout << "]\n"; } while(0)

#define p_map(map,it) do {cout << "{";for (auto (it) = map.begin();;++(it)) {if ((it) == map.end()) {cout << "}\n";break;}else cout << "" << (it)->first << "=>" << (it)->second << ", ";}}while(0)



struct UnionFind {

private:

    vector<int> par,depth;

public:

    UnionFind (int n) {

        par.resize(n);

        depth = vector<int>(n,0);

        for (int i = 0;i < n;++i) par[i] = i;

    }



    int find(int x) {

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

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

    }



    void unite(int x,int y) {

        x = find(x);

        y = find(y);

        if (x == y) return;

        if (depth[x] < depth[y]) par[x] = y;

        else {

            par[y] = x;

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

        }

    }



    bool same(int x,int y) {

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

    }

};



int main() {

    int n,m;

    cin >> n >> m;

    UnionFind uf(n);

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

        int x,y,z;

        cin >> x >> y >> z;

        uf.unite(x-1,y-1);

    }

    set<int> st;

    for (int i = 0;i < n;++i) st.insert(uf.find(i));

    cout << st.size() << endl;

}
// Slower C++ solution:
#include <stdio.h>

#include <vector>

using namespace std;

int n, m;

int x, y, z;

int c;

vector<int> g[100000];

int s[100000];

void dfs(int a, int b) {

	s[a] = 1;

	for (int i = 0; i < g[a].size(); i++) {

		if (g[a][i] != b && s[g[a][i]] == 0)dfs(g[a][i], a);

	}

}

int main() {

	scanf("%d%d", &n, &m);

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

		scanf("%d%d%d", &x, &y, &z);

		x--; y--;

		g[x].push_back(y);

		g[y].push_back(x);

	}

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

		if (s[i] == 0) {

			c++;

			dfs(i, i);

		}

	}

	printf("%d\n", c);

}

// Faster C++ solution for the same problem (measured speedup: 17.400796859354166x):
#include <stdio.h>

int n, m, p, an, bn, ans;

int x[100000];

int y[100000];

int a[100000];

int b[100000];

long long eans[100000];

int root(int c) {

	int t = 0;

	while (x[c] >= 0) {

		y[t] = c;

		c = x[c];

		t++;

	}

	for (int i = 0; i < t - 1; i++) {

		x[y[i]] = c;

	}

	return c;

}

void merge(int c, int d) {

	if (c == d)return;

	if (x[c] < x[d]) {

		x[c] += x[d];

		x[d] = c;

	}

	else if (x[c] == x[d]) {

		x[c] += x[d];

		x[d] = c;

	}

	else{

		x[d] += x[c];

		x[c] = d;

	}

}

int main() {

	scanf("%d%d", &n, &m);

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

		scanf("%d%d%d", a + i, b + i, &p);

		a[i]--, b[i]--;

	}

	for (int i = 0; i < n; i++)x[i] = -1;

	ans = n;

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

		an = root(a[i]);

		bn = root(b[i]);

		if (an != bn) {

			ans--;

			merge(an, bn);

		}

	}

	printf("%d\n", ans);

}
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

//unionfind

typedef pair<int, int> P;

const int MAX_N = 100010;

int m, n;

int par[MAX_N];    //親

int deapth[MAX_N]; //木の深さ

int cnt[MAX_N];

int num;



vector<int> vec[MAX_N];

//n要素で初期化

void init(int n)

{

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

    {

        par[i] = i;

        deapth[i] = 0;

        cnt[i] = 1;

    }

}

//木の根を求める

int find(int x)

{

    if (par[x] == x)

    {

        return x;

    }

    else

    {

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

    }

}



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

void unite(int x, int y)

{

    x = find(x);

    y = find(y);

    if (x == y)

        return;

    if (deapth[x] < deapth[y])

    {

        par[x] = y;

        cnt[y] += cnt[x];

    }

    else

    {

        par[y] = x;

        cnt[x] += cnt[y];

        if (deapth[x] == deapth[y])

            deapth[x]++;

    }

}



bool same(int x, int y)

{

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

}



int main()

{

    cin >> n >> m;

    init(n + 1);

    vector<P> v;

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

    {

        int x, y, z;

        cin >> x >> y >> z;

        unite(x, y);

    }

    int ans = 0;

    vector<bool> fl(n + 1, false);

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

    {

        if (fl[find(i)])

        {

            continue;

        }

        fl[find(i)] = true;

        ans++;

    }

    cout << ans << endl;

}


// Faster C++ solution for the same problem (measured speedup: 3.4907595897833925x):
#include <bits/stdc++.h>

using namespace std;



class UnionFindTree

{

    vector<int> parent;

    vector<int> depth;

    vector<int> cnt;



public:

    UnionFindTree(int n) : parent(n), depth(n), cnt(n)

    {

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

        {

            parent[i] = i;

            depth[i] = 0;

            cnt[i] = 1;

        }

    }



    //木の根を求める

    int find(int x)

    {

        if (parent[x] == x)

        {

            return x;

        }

        else

        {

            return parent[x] = find(parent[x]);

        }

    }



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

    void unite(int x, int y)

    {

        x = find(x);

        y = find(y);

        if (x == y)

            return;

        if (depth[x] < depth[y])

        {

            parent[x] = y;

            cnt[y] += cnt[x];

        }

        else

        {

            parent[y] = x;

            cnt[x] += cnt[y];

            if (depth[x] == depth[y])

                depth[x]++;

        }

    }



    bool same(int x, int y)

    {

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

    }



    int size(int x)

    {

        return cnt[find(x)];

    }

};



int main()

{

    int n, m;

    cin >> n >> m;

    UnionFindTree utree(n + 10);

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

    {

        int x, y, z;

        cin >> x >> y >> z;

        utree.unite(x, y);

    }

    map<int, int> fl;

    int ans = n;

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

    {

        if (!fl[utree.find(i)])

        {

            fl[utree.find(i)] = 1;

            ans -= utree.size(i)-1;

        }

    }

    cout << ans << endl;

}
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

//unionfind

typedef pair<int, int> P;

const int MAX_N = 100010;

int m, n;

int par[MAX_N];    //親

int deapth[MAX_N]; //木の深さ

int cnt[MAX_N];

int num;



vector<int> vec[MAX_N];

//n要素で初期化

void init(int n)

{

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

    {

        par[i] = i;

        deapth[i] = 0;

        cnt[i] = 1;

    }

}

//木の根を求める

int find(int x)

{

    if (par[x] == x)

    {

        return x;

    }

    else

    {

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

    }

}



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

void unite(int x, int y)

{

    x = find(x);

    y = find(y);

    if (x == y)

        return;

    if (deapth[x] < deapth[y])

    {

        par[x] = y;

        cnt[y] += cnt[x];

    }

    else

    {

        par[y] = x;

        cnt[x] += cnt[y];

        if (deapth[x] == deapth[y])

            deapth[x]++;

    }

}



bool same(int x, int y)

{

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

}



int main()

{

    cin >> n >> m;

    init(n + 1);

    vector<P> v;

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

    {

        int x, y, z;

        cin >> x >> y >> z;

        unite(x, y);

    }

    int ans = 0;

    vector<bool> fl(n + 1, false);

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

    {

        if (fl[find(i)])

        {

            continue;

        }

        fl[find(i)] = true;

        ans++;

    }

    cout << ans << endl;

}


// Faster C++ solution for the same problem (measured speedup: 3.4899025087335294x):
#include <bits/stdc++.h>

using namespace std;



class UnionFindTree

{

    vector<int> parent;

    vector<int> depth;

    vector<int> cnt;



public:

    UnionFindTree(int n) : parent(n), depth(n), cnt(n)

    {

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

        {

            parent[i] = i;

            depth[i] = 0;

            cnt[i] = 1;

        }

    }



    //木の根を求める

    int find(int x)

    {

        if (parent[x] == x)

        {

            return x;

        }

        else

        {

            return parent[x] = find(parent[x]);

        }

    }



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

    void unite(int x, int y)

    {

        x = find(x);

        y = find(y);

        if (x == y)

            return;

        if (depth[x] < depth[y])

        {

            parent[x] = y;

            cnt[y] += cnt[x];

        }

        else

        {

            parent[y] = x;

            cnt[x] += cnt[y];

            if (depth[x] == depth[y])

                depth[x]++;

        }

    }



    bool same(int x, int y)

    {

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

    }



    int size(int x)

    {

        return cnt[find(x)];

    }

};



int main()

{

    int n, m;

    cin >> n >> m;

    UnionFindTree utree(n + 10);

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

    {

        int x, y, z;

        cin >> x >> y >> z;

        utree.unite(x, y);

    }

    map<int, int> fl;

    int ans = 0;

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

    {

        if (!fl[utree.find(i)])

        {

            fl[utree.find(i)] = 1;

            ans++;

        }

    }

    cout << ans << endl;

}