#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int SIZE = 100;
int G[SIZE][SIZE];
int GT[SIZE][SIZE];
bool visit[SIZE];
int parent[SIZE];
vector< int >vec;
int nodes;
int edges;
void init(){
int source, target;
memset( G, 0, sizeof( G ) );
memset( GT, 0, sizeof( GT ) );
cin >> nodes >> edges;
for( int edge = 1; edge <= edges; ++edge ){
cin >> source >> target;
G[source][target] = 1;
G[target][source] = 1;
}
}
void DFS_G( int cur ){
visit[cur] = true;
for( int node = 1; node <= nodes; ++node ){
if( G[cur][node] && !visit[node] )
DFS_G( node );
}
vec.push_back( cur );
}
void DFS_GT( int cur, const int& par ){
visit[cur] = true;
parent[cur] = par;
for( int node = 1; node <= nodes; ++node ){
if( GT[cur][node] && !visit[node] )
DFS_GT( node, par );
}
}
void Kosaraju(){
int node;
int count = 0;
init();
memset( visit, false, sizeof( visit ) );
for( node = 1; node <= nodes; ++node ){
if( !visit[node] )
DFS_G( node );
}
memset( visit, false, sizeof( visit ) );
for( node = nodes; node >= 1; --node ){
if( !visit[vec[node - 1]] ){
DFS_GT( vec[node - 1], count );
count++;
}
}
cout << count << endl;
}
int main(){
Kosaraju();
return 0;
}