// Code written by JadeMasochist
#include <bits/stdc++.h>
using namespace std;
#define LL long long
typedef vector<LL> vi;
LL n, m, SCCcnt = 0; // Basic variables.
LL Time = 0; // Used to track the traversing order.
vector<vi> adj; vi Lowest, Enum; // Store essential informations.
// adj: Adjacency lists.
// Enum: The traversing position of a node.
// Lowest: The lowest position of any nodes within the same SCC as the current one.
stack<LL> S; // Keep the currently working nodes (incomplete SCC).
void traverse(LL z) {
Lowest[z] = ++Time; Enum[z] = Time; S.push(z);
for (LL i=0; i<adj[z].size(); i++) {
if (Enum[adj[z][i]] != 0) Lowest[z] = min(Lowest[z], Lowest[adj[z][i]]); // Traversed node - update Lowest value.
else {
traverse(adj[z][i]); // Untraversed node, so traverse it.
Lowest[z] = min(Lowest[z], Lowest[adj[z][i]]); // Update the new Lowest value.
}
}
if (Enum[z] == Lowest[z]) { // Lowest node found - SCC completed
SCCcnt++; LL t;
do {
t = S.top(); S.pop();
Lowest[t] = 1e18; Enum[t] = 1e18; // Remove every vertex on the SCC out of traversion.
}
while (z != t);
}
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> m; adj.resize(n+1, vi(0));
while (m--) {
LL u, v; cin >> u >> v;
adj[u].push_back(v);
}
Lowest.resize(n+1, 0); Enum = Lowest;
for (LL i=1; i<=n; i++) {
if (Lowest[i] == 0) traverse(i);
}
cout << SCCcnt;
return 0;
}
Ly8gQ29kZSB3cml0dGVuIGJ5IEphZGVNYXNvY2hpc3QKCiNpbmNsdWRlIDxiaXRzL3N0ZGMrKy5oPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKI2RlZmluZSBMTCBsb25nIGxvbmcKdHlwZWRlZiB2ZWN0b3I8TEw+IHZpOwoKCkxMIG4sIG0sIFNDQ2NudCA9IDA7IC8vIEJhc2ljIHZhcmlhYmxlcy4KTEwgVGltZSA9IDA7IC8vIFVzZWQgdG8gdHJhY2sgdGhlIHRyYXZlcnNpbmcgb3JkZXIuCnZlY3Rvcjx2aT4gYWRqOyB2aSBMb3dlc3QsIEVudW07IC8vIFN0b3JlIGVzc2VudGlhbCBpbmZvcm1hdGlvbnMuCgkvLyBhZGo6IEFkamFjZW5jeSBsaXN0cy4KCS8vIEVudW06IFRoZSB0cmF2ZXJzaW5nIHBvc2l0aW9uIG9mIGEgbm9kZS4KCS8vIExvd2VzdDogVGhlIGxvd2VzdCBwb3NpdGlvbiBvZiBhbnkgbm9kZXMgd2l0aGluIHRoZSBzYW1lIFNDQyBhcyB0aGUgY3VycmVudCBvbmUuCnN0YWNrPExMPiBTOyAvLyBLZWVwIHRoZSBjdXJyZW50bHkgd29ya2luZyBub2RlcyAoaW5jb21wbGV0ZSBTQ0MpLgoKdm9pZCB0cmF2ZXJzZShMTCB6KSB7CglMb3dlc3Rbel0gPSArK1RpbWU7IEVudW1bel0gPSBUaW1lOyBTLnB1c2goeik7Cglmb3IgKExMIGk9MDsgaTxhZGpbel0uc2l6ZSgpOyBpKyspIHsKCQlpZiAoRW51bVthZGpbel1baV1dICE9IDApIExvd2VzdFt6XSA9IG1pbihMb3dlc3Rbel0sIExvd2VzdFthZGpbel1baV1dKTsgLy8gVHJhdmVyc2VkIG5vZGUgLSB1cGRhdGUgTG93ZXN0IHZhbHVlLgoJCWVsc2UgewoJCQl0cmF2ZXJzZShhZGpbel1baV0pOyAvLyBVbnRyYXZlcnNlZCBub2RlLCBzbyB0cmF2ZXJzZSBpdC4KCQkJTG93ZXN0W3pdID0gbWluKExvd2VzdFt6XSwgTG93ZXN0W2Fkalt6XVtpXV0pOyAvLyBVcGRhdGUgdGhlIG5ldyBMb3dlc3QgdmFsdWUuCgkJfQoJfQoJCglpZiAoRW51bVt6XSA9PSBMb3dlc3Rbel0pIHsgLy8gTG93ZXN0IG5vZGUgZm91bmQgLSBTQ0MgY29tcGxldGVkCgkJU0NDY250Kys7IExMIHQ7CgkJZG8gewoJCQl0ID0gUy50b3AoKTsgUy5wb3AoKTsKCQkJTG93ZXN0W3RdID0gMWUxODsgRW51bVt0XSA9IDFlMTg7IC8vIFJlbW92ZSBldmVyeSB2ZXJ0ZXggb24gdGhlIFNDQyBvdXQgb2YgdHJhdmVyc2lvbi4KCQl9CgkJd2hpbGUgKHogIT0gdCk7Cgl9Cn0KCmludCBtYWluKCkgewoJaW9zX2Jhc2U6OnN5bmNfd2l0aF9zdGRpbygwKTsKCWNpbi50aWUoMCk7IGNvdXQudGllKDApOwoJY2luID4+IG4gPj4gbTsgYWRqLnJlc2l6ZShuKzEsIHZpKDApKTsKCXdoaWxlIChtLS0pIHsKCQlMTCB1LCB2OyBjaW4gPj4gdSA+PiB2OwoJCWFkalt1XS5wdXNoX2JhY2sodik7Cgl9CglMb3dlc3QucmVzaXplKG4rMSwgMCk7IEVudW0gPSBMb3dlc3Q7Cglmb3IgKExMIGk9MTsgaTw9bjsgaSsrKSB7CgkJaWYgKExvd2VzdFtpXSA9PSAwKSB0cmF2ZXJzZShpKTsKCX0KCWNvdXQgPDwgU0NDY250OwkKCXJldHVybiAwOwp9