//ALEX ENACHE
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <unordered_map>
#include <time.h>
#include <iomanip>
#include <deque>
#include <math.h>
#include <cmath>
#include <assert.h>
#include <stack>
#include <bitset>
#include <random>
#include <chrono>
using namespace std;
//#include <iostream>
#include <fstream>
ifstream cin ("dfs.in");ofstream cout ("dfs.out");
vector < int > gr[100100];
stack < int > q;
bool used[100100];
int main() {
//freopen("input", "r", stdin);freopen("output", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cout << setprecision(10) << fixed;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
srand(time(NULL));
//citesc datele
int noduri , muchii;
cin>>noduri>>muchii;
//citesc muchiile
for (int i=1; i<=muchii; i++){
int x , y;
cin>>x>>y;
//trag muchie
gr[x].push_back(y);
gr[y].push_back(x);
}
int cont = 0;
for (int sursa=1; sursa<=noduri; sursa++){
if (used[sursa]){
continue;
}
cont++;
q.push(sursa);
used[sursa] = true;
//cat timp nu e goala coada
while (!q.empty()){
int nod = q.top();
q.pop();
for (int i=0; i<gr[nod].size(); i++){
if (!used[gr[nod][i]]){
q.push(gr[nod][i]);
used[gr[nod][i]] = true;
}
}
}
}
//afisez nr de componente conexe
cout<<cont;
return 0;
}