#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
// Global variables
vector<int> adj[1000005]; // Adjacency list as array of vectors
int ids[1000005]; // Discovery times array
int low[1000005]; // Lowest reachable vertex id array
bool onStack[1000005]; // Tracks vertices in current SCC array
stack<int> st; // Stack for DFS
int id = 0; // Current discovery time
int sccCount = 0; // Count of SCCs
int n; // Number of vertices
void dfs(int at) {
ids[at] = low[at] = id++;
st.push(at);
onStack[at] = true;
// Visit all neighbors
for (int to : adj[at]) {
if (ids[to] == -1) {
dfs(to);
low[at] = min(low[at], low[to]);
}
else if (onStack[to])
low[at] = min(low[at], ids[to]);
}
// Found an SCC
if (ids[at] == low[at]) {
while (!st.empty()) {
int node = st.top();
st.pop();
onStack[node] = false;
low[node] = ids[at];
if (node == at) break;
}
sccCount++;
}
}
int findSCC() {
for (int i = 0; i < n; i++)
if (ids[i] == -1)
dfs(i);
return sccCount;
}
void initialize(int vertices) {
n = vertices;
for (int i = 0; i < n; i++) {
adj[i].clear();
ids[i] = -1;
low[i] = 0;
onStack[i] = false;
}
id = 0 = sccCount = 0;
while (!st.empty()) st.pop(); // Clear stack
}
int main() {
int m; // Number of edges
cin >> n >> m; // Input number of vertices and edges
initialize(n);
// Input m edges
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
// Assuming 0-based indexing
adj[u].push_back(v);
}
int result = findSCC();
cout << "Number of Strongly Connected Components: " <<
result << endl;
return 0;
}