#include <fstream>
#include <vector>
#include <stack>
#include <iostream>
using namespace std;
///// DESCRIPTION
// THIS PROGRAM EMPLOYS DEPTH-FIRST SEARCH
// ON AN INPUT OF AN UNDIRECTED GRAPH
// WITH N VERTICES AND M EDGES
// TO DETERMINE HOW MANY
// CONNECTED COMPONENTS IT HAS
/////
void dfs(int, vector<int>[], bool[], stack<int>);
int main(int argc, char **argv)
{
// INPUT
ifstream indata("dfs.in");
int n, m;
indata >> n >> m;
vector<int> edges[n + 1];
for (int i = 0, x, y; i < m; i++) {
indata >> x >> y;
// there is a path from x to y
edges[x].push_back(y);
}
// DFS
bool visited[n + 1];
for (int i = 1; i <= n; i++) {
visited[i] = false;
}
int connectedComponents = 0;
for (int i = 1; i <= n; i++) {
if (visited[i] == true) {
continue;
}
// if this node has not been visited
// by doing dfs on another one already
// then it belongs to a different
// connected element
connectedComponents++;
// mark every node in this connected
// element as visited
stack<int> stack;
dfs(i, edges, visited, stack);
}
// OUTPUT
ofstream outdata("dfs.out");
outdata << connectedComponents;
outdata.close();
return 0;
}
void dfs(int currentNode, vector<int> edges[], bool visited[], stack<int> stack) {
// mark current node as visited
visited[currentNode] = true;
// add all unvisited nodes to the stack
for (size_t i = 0; i < edges[currentNode].size(); i++) {
if (visited[edges[currentNode][i]] == false) {
stack.push(edges[currentNode][i]);
}
}
// if there still are unvisited elements on the stack,
// visit the next one
if (stack.size() != 0) {
int nextNode = stack.top();
stack.pop();
dfs(nextNode, edges, visited, stack);
}
}