        // be name khoda
        // never give up :))))
        #include <bits/stdc++.h>
        #define mp make_pair
        #define f1 first
        #define f2 second
        #define int long long int
        #define pb push_back
        #define pii pair<ll ,ll>
        #define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        using namespace std;
        const int mox=1e5+9;
        vector <int> v[mox];
        bool visit[mox];
        bool ed[mox];
        bool visit2[mox];
        bool visit3[mox];
        bool visit4[mox];
        int u=0;
        int p=0;
        stack <int> s;
        vector <int> w[mox];
        int l=0;
        vector <int> va[mox];
        int lo[mox];
        vector <int> ah;
        bool visit5[mox];
        bool ed2[mox];
        void dfs(int x)
        {
            visit[x]=1;
            for(int i:v[x])
            {
                if(visit[i]==0)
                {
                    dfs(i);
                }
            }
            s.push(x);
        }
        void dfs2(int x)
        {
            visit2[x]=1;
            u+=1;
            for(int i:v[x])
            {
                if(visit2[i]==0)
                {
                    dfs2(i);
                }
                else if(ed[i]==0)
                {
                    p=1;
                }
            }
            ed[x]=1;
            w[l].pb(x);
            lo[x]=l;
        }
        void dfs3(int x)
        {
            u+=1;
            visit5[x]=1;
            for(int i:va[x])
            {
                if(visit5[i]==0)
                {
                    dfs3(i);
                }
            }
        }
        main()
        {
            int n,m;
            cin>>n>>m;
            for(int i=0 ; i<m ; i++)
            {
                int a,b;
                cin>>a>>b;
                v[a].pb(b);
            }
            int ans=0;
            for(int i=1 ; i<=n ; i++)
            {
                if(visit[i]==0)
                {
                    dfs(i);
                }
            }
            while(s.empty()==0)
            {
                int v=s.top();
                s.pop();
                if(visit2[v]==0)
                {
                    dfs2(v);
                    if(p==1)
                    ans+=1;
                    p=0;
                    ans+=u-1;
                    u=0;
                    l+=1;
                }
            }
            for(int i=l-1 ; i>=0 ; i--)
            {
                for(int j:w[i])
                {
                    for(int t:v[j])
                    {
                        if(visit3[lo[t]]==0)
                        {
                            visit3[lo[t]]=1;
                            va[lo[t]].pb(i);

                        }
                    }
                }
                 for(int j:w[i])
                {
                    for(int t:v[j])
                    {
                        if(visit3[lo[t]]==1)
                        {
                            visit3[lo[t]]=0;
                        }
                    }
                }

            }
             for(int i=0 ; i<l ; i++)
            {
                if(visit5[i]==0)
                {
                    dfs3(i);
                    ans+=u-1;
                    u=0;
                }
            }
            cout<<ans;
        }


    // be name khoda
    // never give up :))))
    #include <bits/stdc++.h>
    #define mp make_pair
    #define f1 first
    #define f2 second
    #define int long long int
    #define pb push_back
    #define pii pair<ll ,ll>
    #define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    using namespace std;
    const int mox=1e5+9;
    vector <int> v[mox];
    bool visit[mox];
    bool ed[mox];
    bool visit2[mox];
    bool visit3[mox];
    bool visit4[mox];
    int u=0;
    int p=0;
    stack <int> s;
    vector <int> w[mox];
    int l=0;
    vector <int> va[mox];
    int lo[mox];
    vector <int> ah;
    bool visit5[mox];
    void dfs(int x)
    {
        visit[x]=1;
        for(int i:v[x])
        {
            if(visit[i]==0)
            {
                dfs(i);
            }
        }
        s.push(x);
    }
    void dfs2(int x)
    {
        visit2[x]=1;
        u+=1;
        for(int i:v[x])
        {
            if(visit2[i]==0)
            {
                dfs2(i);
            }
            else if(ed[i]==0)
            {
                p=1;
            }
        }
        ed[x]=1;
        w[l].pb(x);
        lo[x]=l;
    }
    void dfs3(int x)
    {
        visit4[x]=1;
        u+=1;
        ah.pb(x);
        visit5[x]=1;
        for(int i:va[x])
        {
            if(visit5[i]==0&&ed[i]==0)
            {
                dfs3(i);
            }
            else if(ed[i]==1&&visit4[i]==0&&visit5[i]==1)
            {
                u+=1;
              visit4[i]=1;
              ah.pb(i);
            }
        }
        ed[x]=1;
    }
    main()
    {
        int n,m;
        cin>>n>>m;
        for(int i=0 ; i<m ; i++)
        {
            int a,b;
            cin>>a>>b;
            v[a].pb(b);
        }
        int ans=0;
        for(int i=1 ; i<=n ; i++)
        {
            if(visit[i]==0)
            {
                dfs(i);
            }
        }
        while(s.empty()==0)
        {
            int v=s.top();
            s.pop();
            if(visit2[v]==0)
            {
                dfs2(v);
                if(p==1)
                ans+=1;
                p=0;
                ans+=u-1;
                u=0;
                l+=1;
            }
        }
        for(int i=l-1 ; i>=0 ; i--)
        {
            for(int j:w[i])
            {
                for(int t:v[j])
                {
                    if(visit3[lo[t]]==0)
                    {
                        visit3[lo[t]]=1;
                        va[i].pb(lo[t]);
                    }
                }
            }
             for(int j:w[i])
            {
                for(int t:v[j])
                {
                    if(visit3[lo[t]]==1)
                    {
                        visit3[lo[t]]=0;
                    }
                }
            }
        }
         for(int i=l-1 ; i>=0 ; i--)
        {
            if(visit5[i]==0)
            {
                dfs3(i);
                ans+=u-1;
                u=0;
                for(int j:ah)
                    visit4[j]=0;
                    ah.clear();
            }
        }
        cout<<ans;
    }


#include <bits/stdc++.h>
#define mp make_pair
#define f1 first
#define f2 second
#define int long long
#define pb push_back
#define pii pair<int ,int>
#define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
int const mox=1e5+9;
vector <int> v[mox];
int l;
bool visit[mox],visit2[mox];
int ed[mox];
vector <int> la[mox];
vector <int> vr[mox];
void dfs(int x)
{
    visit[x]=1;
    for(int i:v[x])
    {
        if(visit[i]==0)
            dfs(i);
    }
    la[l].pb(x);
}
bool dfs2(int x)
{
    visit2[x]=1;
    for(int i:vr[x])
    {
        if(visit2[i]==0)
            dfs2(i);
        else if(ed[i]==0)
            return 0;
    }
    ed[x]=1;
    return 1;
}
main()
{
      ios
    int n,m;
    cin>>n>>m;
    for(int i=0 ; i<m ; i++)
    {
        int a,b;
        cin>>a>>b;
        v[a].pb(b);
        v[b].pb(a);
        vr[a].pb(b);
    }
    for(int i=0 ; i<n ; i++)
    {
        if(visit[i]==0)
        {
            dfs(i);
            l+=1;
        }
    }
    int ans=0;
    for(int i=0 ; i<l ; i++)
    {   bool fo=0;
        for(int j:la[i])
        {
            if(visit2[j]==0)
            {
                if(dfs2(j)==0)
                    fo=1;
            }
        }
        if(fo==1)
            ans+=la[i].size();
        else
            ans+=la[i].size()-1;
    }
    cout<<ans;
}


    // be name khoda
    // never give up :))))
    #include <bits/stdc++.h>
    #define mp make_pair
    #define f1 first
    #define f2 second
    #define int long long int
    #define pb push_back
    #define pii pair<ll ,ll>
    #define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    using namespace std;
    const int mox=1e5+9;
    vector <int> v[mox];
    bool visit[mox];
    bool ed[mox];
    bool visit2[mox];
    bool visit3[mox];
    bool visit4[mox];
    int u=0;
    int p=0;
    stack <int> s;
    vector <int> w[mox];
    int l=0;
    vector <int> va[mox];
    int lo[mox];
    vector <int> ah;
    bool visit5[mox];
    void dfs(int x)
    {
        visit[x]=1;
        for(int i:v[x])
        {
            if(visit[i]==0)
            {
                dfs(i);
            }
        }
        s.push(x);
    }
    void dfs2(int x)
    {
        visit2[x]=1;
        u+=1;
        for(int i:v[x])
        {
            if(visit2[i]==0)
            {
                dfs2(i);
            }
            else if(ed[i]==0)
            {
                p=1;
            }
        }
        ed[x]=1;
        w[l].pb(x);
        lo[x]=l;
    }
    void dfs3(int x)
    {
        visit4[x]=1;
        u+=1;
        ah.pb(x);
        visit5[x]=1;
        for(int i:va[x])
        {
            if(visit5[i]==0&&ed[i]==0)
            {
                dfs3(i);
            }
            else if(ed[i]==1&&visit4[i]==0&&visit5[i]==1)
            {
                u+=1;
              visit4[i]=1;
              ah.pb(i);
            }
        }
        ed[x]=1;
    }
    main()
    {
        int n,m;
        cin>>n>>m;
        for(int i=0 ; i<m ; i++)
        {
            int a,b;
            cin>>a>>b;
            v[a].pb(b);
        }
        int ans=0;
        for(int i=1 ; i<=n ; i++)
        {
            if(visit[i]==0)
            {
                dfs(i);
            }
        }
        while(s.empty()==0)
        {
            int v=s.top();
            s.pop();
            if(visit2[v]==0)
            {
                dfs2(v);
                if(p==1)
                ans+=1;
                p=0;
                ans+=u-1;
                u=0;
                l+=1;
            }
        }
        for(int i=l-1 ; i>=0 ; i--)
        {
            for(int j:w[i])
            {
                for(int t:v[j])
                {
                    if(visit3[lo[t]]==0)
                    {
                        visit3[lo[t]]=1;
                        va[i].pb(lo[t]);
                    }
                }
            }
             for(int j:w[i])
            {
                for(int t:v[j])
                {
                    if(visit3[lo[t]]==1)
                    {
                        visit3[lo[t]]=0;
                    }
                }
            }
        }
         for(int i=0 ; i<l ; i++)
        {
            if(visit5[i]==0)
            {
                dfs3(i);
                ans+=u-1;
                u=0;
                for(int j:ah)
                    visit4[j]=0;
            }
        }
        cout<<ans;
    }


// be name khoda
// never give up :))))
#include <bits/stdc++.h>
#define mp make_pair
#define f1 first
#define f2 second
#define int long long int
#define pb push_back
#define pii pair<ll ,ll>
#define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int mox=1e5+9;
vector <int> v[mox];
bool visit[mox];
bool ed[mox];
bool visit2[mox];
bool visit3[mox];
bool visit4[mox];
int u=0;
int p=0;
stack <int> s;
vector <int> w[mox];
int l=0;
vector <int> va[mox];
int lo[mox];
vector <int> ah;
void dfs(int x)
{
    visit[x]=1;
    for(int i:v[x])
    {
        if(visit[i]==0)
        {
            dfs(i);
        }
    }
    s.push(x);
}
void dfs2(int x)
{
    visit2[x]=1;
    u+=1;
    for(int i:v[x])
    {
        if(visit2[i]==0)
        {
            dfs2(i);
        }
        else if(ed[i]==0)
        {
            p=1;
        }
    }
    ed[x]=1;
    w[l].pb(x);
    lo[x]=l;
}
void dfs3(int x)
{
    visit4[x]=1;
    u+=1;
    ah.pb(x);
    for(int i:va[x])
    {
        if(visit4[i]==0&&ed[i]==0)
        {
            dfs3(i);
        }
        else if(ed[x]==1&&visit4[i]==0)
        {
            u+=1;
          visit4[i]=1;
        }
    }
    ed[x]=1;
}
main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0 ; i<m ; i++)
    {
        int a,b;
        cin>>a>>b;
        v[a].pb(b);
    }
    int ans=0;
    for(int i=1 ; i<=n ; i++)
    {
        if(visit[i]==0)
        {
            dfs(i);
        }
    }
    while(s.empty()==0)
    {
        int v=s.top();
        s.pop();
        if(visit2[v]==0)
        {
            dfs2(v);
            if(p==1)
            ans+=1;
            p=0;
            ans+=u-1;
            u=0;
            l+=1;
        }
    }
    for(int i=l-1 ; i>=0 ; i--)
    {
        for(int j:w[i])
        {
            for(int t:v[j])
            {
                if(visit3[lo[t]]==0)
                {
                    visit3[lo[t]]=1;
                    va[i].pb(lo[t]);
                }
            }
        }
         for(int j:w[i])
        {
            for(int t:v[j])
            {
                if(visit3[lo[t]]==1)
                {
                    visit3[lo[t]]=0;
                }
            }
        }
    }
     for(int i=l-1 ; i>=0 ; i--)
    {
        if(visit4[i]==0)
        {
            dfs3(i);
            ans+=u-1;
            u=0;
            for(int j:ah)
                visit4[j]=0;
        }
    }
    cout<<ans;
}


// be name khoda
// never give up :))))
#include <bits/stdc++.h>
#define mp make_pair
#define f1 first
#define f2 second
#define int long long int
#define pb push_back
#define pii pair<ll ,ll>
#define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int mox=1e5+9;
vector <int> v[mox];
bool visit[mox];
bool ed[mox];
bool p=0;
int u=0;
void dfs(int x)
{
    visit[x]=1;
    u+=1;
    for(int i:v[x])
    {
        if(visit[i]==0)
        {
            dfs(i);
        }
        else if(ed[i]==0)
        {
            p=1;
        }
    }
    ed[x]=1;
}
main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0 ; i<m ; i++)
    {
        int a,b;
        cin>>a>>b;
        v[a].pb(b);
    }
    int ans=0;
    for(int i=1 ; i<=n ; i++)
    {
        if(visit[i]==0)
        {
            dfs(i);
            if(p==0)
                ans+=u-1;
            else
                ans+=u;
            p=0;
            u=0;
        }
    }
    cout<<ans;
}


// be name khoda
// never give up :))))
#include <bits/stdc++.h>
#define mp make_pair
#define f1 first
#define f2 second
#define int long long int
#define pb push_back
#define pii pair<ll ,ll>
#define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int mox=1e5+9;
map<int ,int > ma[2];
vector <pii> v[mox][2];
vector <pii<pii , pii> > g;
map < pii<pii,pii> , int > h;
int dad[mox];
int fnd(int x)
{
    if(dad[x]==0)
        return x;
    else
    {
        dad[x]=fnd(dad[x]);
        return dad[x];
    }
}
int uoin(int x,int y)
{
    int h=fnd(x);
    int p=fnd(y);
    if(h!=p)
    {
        dad[h]=p;
    }
}
main()
{
    int n;
    cin>>n;
    int o=1,o2=1;
    int u=1;
    for(int i=0 ; i<n ; i++)
    {
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        if(ma[y1][0]==0)
        {
            ma[y]=o;
            o+=1;
        }
        if(ma[y2][1]==0)
        {
            ma[y2][1]=o2;
            o2+=1;
        }
     v[ma[y1]][0].pb(mp(x1,x2));
     v[ma[y2]][1].pb(mp(x1,x2));
     g.pb(mp(mp(y1,y2),mp(x1,x2)));
     h[mp(mp(x1,y1),mp(x2,y2))]=u;
     u+=1;
    }
    for(int i=1 ; i<o ; i++)
    {
        sort(v[i][0].begin(),v[i][0].end());
    }
    for(int i=1 ; i<o2 ; i++)
    {
        sort(v[i][1].begin(),v[i][0].end());
    }
    for(pii i :g)
    {
        for(pii j:v[ma[i.f1.f1]][0])
        {

        }
    }

}


// be name khoda
// never give up :))))
#include <bits/stdc++.h>
#define mp make_pair
#define f1 first
#define f2 second
#define int long long int
#define pb push_back
#define pii pair<ll ,ll>
#define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int mox=1e5+9;
vector <int> v[mox];
bool visit[mox];
bool ed[mox];
bool visit2[mox];
bool visit3[mox];
bool visit4[mox];
int u=0;
int p=0;
stack <int> s;
vector <int> w[mox];
int l=0;
vector <int> va[mox];
int lo[mox];
void dfs(int x)
{
    visit[x]=1;
    for(int i:v[x])
    {
        if(visit[i]==0)
        {
            dfs(i);
        }
    }
    s.push(x);
}
void dfs2(int x)
{
    visit2[x]=1;
    u+=1;
    for(int i:v[x])
    {
        if(visit2[i]==0)
        {
            dfs2(i);
        }
        else if(ed[i]==0)
        {
            p=1;
        }
    }
    ed[x]=1;
    w[l].pb(x);
    lo[x]=l;
}
void dfs3(int x)
{
    visit4[x]=1;
    u+=1;
    for(int i:va[x])
    {
        if(visit4[i]==0)
        {
            dfs3(i);
        }
    }
}
main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0 ; i<m ; i++)
    {
        int a,b;
        cin>>a>>b;
        v[a].pb(b);
    }
    int ans=0;
    for(int i=1 ; i<=n ; i++)
    {
        if(visit[i]==0)
        {
            dfs(i);
        }
    }
    while(s.empty()==0)
    {
        int v=s.top();
        s.pop();
        if(visit2[v]==0)
        {
            dfs2(v);
            if(p==1)
            ans+=1;
            p=0;
            ans+=u-1;
            u=0;
            l+=1;
        }
    }
    for(int i=l-1 ; i>=0 ; i--)
    {
        for(int j:w[i])
        {
            for(int t:v[j])
            {
                if(visit3[lo[t]]==0)
                {
                    visit3[lo[t]]=1;
                    va[i].pb(lo[t]);
                }
            }
        }
         for(int j:w[i])
        {
            for(int t:v[j])
            {
                if(visit3[lo[t]]==1)
                {
                    visit3[lo[t]]=0;
                }
            }
        }
    }
     for(int i=l-1 ; i>=0 ; i--)
    {
        if(visit4[i]==0)
        {
            dfs3(i);
            ans+=u-1;
            u=0;
        }
    }
    cout<<ans;
}


// be name khoda
// never give up :))))
#include <bits/stdc++.h>
#define mp make_pair
#define f1 first
#define f2 second
#define int long long int
#define pb push_back
#define pii pair<ll ,ll>
#define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int mox=1e5+9;
vector <int> v[mox];
bool visit[mox];
bool ed[mox];
bool visit2[mox];
int u=0;
int p=0;
stack <int> s;
void dfs(int x)
{
    visit[x]=1;
    for(int i:v[x])
    {
        if(visit[i]==0)
        {
            dfs(i);
        }
    }
    s.push(x);
}
void dfs2(int x)
{
    visit2[x]=1;
    u+=1;
    for(int i:v[x])
    {
        if(visit2[i]==0)
        {
            dfs2(i);
        }
        else if(ed[i]==0)
        {
            p=1;
        }
        else if(visit2[i]==1&&ed[i]==1)
        {
            u+=1;
        }
    }
    ed[x]=1;
}
main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0 ; i<m ; i++)
    {
        int a,b;
        cin>>a>>b;
        v[a].pb(b);
    }
    int ans=0;
    for(int i=1 ; i<=n ; i++)
    {
        if(visit[i]==0)
        {
            dfs(i);
        }
    }
    while(s.empty()==0)
    {
        int v=s.top();
        s.pop();
        if(visit2[v]==0)
        {
            dfs2(v);
            if(p==1)
            ans+=1;
            p=0;
            ans+=u-1;
            u=0;
        }
    }
    cout<<ans;
}


    // be name khoda
    // never give up :))))
    #include <bits/stdc++.h>
    #define mp make_pair
    #define f1 first
    #define f2 second
    #define int long long int
    #define pb push_back
    #define pii pair<ll ,ll>
    #define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    using namespace std;
    const int mox=1e5+9;
    vector <int> v[mox];
    bool visit[mox];
    bool ed[mox];
    bool visit2[mox];
    bool visit3[mox];
    bool visit4[mox];
    int u=0;
    int p=0;
    stack <int> s;
    vector <int> w[mox];
    int l=0;
    vector <int> va[mox];
    int lo[mox];
    vector <int> ah;
    bool visit5[mox];
    void dfs(int x)
    {
        visit[x]=1;
        for(int i:v[x])
        {
            if(visit[i]==0)
            {
                dfs(i);
            }
        }
        s.push(x);
    }
    void dfs2(int x)
    {
        visit2[x]=1;
        u+=1;
        for(int i:v[x])
        {
            if(visit2[i]==0)
            {
                dfs2(i);
            }
            else if(ed[i]==0)
            {
                p=1;
            }
        }
        ed[x]=1;
        w[l].pb(x);
        lo[x]=l;
    }
    void dfs3(int x)
    {
        visit4[x]=1;
        u+=1;
        ah.pb(x);
        visit5[x]=1;
        for(int i:va[x])
        {
            if(visit5[i]==0&&ed[i]==0)
            {
                dfs3(i);
            }
            else if(ed[i]==1&&visit4[i]==0&&visit5[i]==1)
            {
                u+=1;
              visit4[i]=1;
              ah.pb(i);
            }
        }
        ed[x]=1;
    }
    main()
    {
        int n,m;
        cin>>n>>m;
        for(int i=0 ; i<m ; i++)
        {
            int a,b;
            cin>>a>>b;
            v[a].pb(b);
        }
        int ans=0;
        for(int i=1 ; i<=n ; i++)
        {
            if(visit[i]==0)
            {
                dfs(i);
            }
        }
        while(s.empty()==0)
        {
            int v=s.top();
            s.pop();
            if(visit2[v]==0)
            {
                dfs2(v);
                if(p==1)
                ans+=1;
                p=0;
                ans+=u-1;
                u=0;
                l+=1;
            }
        }
        for(int i=l-1 ; i>=0 ; i--)
        {
            for(int j:w[i])
            {
                for(int t:v[j])
                {
                    if(visit3[lo[t]]==0)
                    {
                        visit3[lo[t]]=1;
                        va[i].pb(lo[t]);
                    }
                }
            }
             for(int j:w[i])
            {
                for(int t:v[j])
                {
                    if(visit3[lo[t]]==1)
                    {
                        visit3[lo[t]]=0;
                    }
                }
            }
        }
         for(int i=l-1 ; i>=0 ; i--)
        {
            if(visit5[i]==0)
            {
                dfs3(i);
                ans+=u-1;
                u=0;
                for(int j:ah)
                    visit4[j]=0;
            }
        }
        cout<<ans;
    }


        // be name khoda
        // never give up :))))
        #include <bits/stdc++.h>
        #define mp make_pair
        #define f1 first
        #define f2 second
        #define int long long int
        #define pb push_back
        #define pii pair<ll ,ll>
        #define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        using namespace std;
        const int mox=1e5+9;
        vector <int> v[mox];
        bool visit[mox];
        bool ed[mox];
        bool visit2[mox];
        bool visit3[mox];
        int u=0;
        int p=0;
        stack <int> s;
        vector <int> w[mox];
        int l=0;
        int lo[mox];
        int ans;
        int dad[mox];
        void dfs(int x)
        {
            visit[x]=1;
            for(int i:v[x])
            {
                if(visit[i]==0)
                {
                    dfs(i);
                }
            }
            s.push(x);
        }
        void dfs2(int x)
        {
            visit2[x]=1;
            u+=1;
            for(int i:v[x])
            {
                if(visit2[i]==0)
                {
                    dfs2(i);
                }
                else if(ed[i]==0)
                {
                    p=1;
                }
            }
            ed[x]=1;
            w[l].pb(x);
            lo[x]=l;
        }
        int fnd (int x)
        {
            if(dad[x]==0)
                return x;
            else
            {
                dad[x]=(fnd(dad[x]));
                return dad[x];
            }
        }
        int uoin(int x ,int y)
        {
           int h=fnd(x);
           int u=fnd(y);
           if(u!=h)
           {
               dad[u]=h;
               ans+=1;
           }
        }
        main()
        {
            int n,m;
            cin>>n>>m;
            for(int i=0 ; i<m ; i++)
            {
                int a,b;
                cin>>a>>b;
                v[a].pb(b);
            }
            for(int i=1 ; i<=n ; i++)
            {
                if(visit[i]==0)
                {
                    dfs(i);
                }
            }
            while(s.empty()==0)
            {
                int v=s.top();
                s.pop();
                if(visit2[v]==0)
                {
                    dfs2(v);
                    if(p==1)
                    ans+=1;
                    p=0;
                    ans+=u-1;
                    u=0;
                    l+=1;
                }
            }
            for(int i=l-1 ; i>=0 ; i--)
            {
                for(int j:w[i])
                {
                    visit3[lo[j]]=1;
                }
                for(int j:w[i])
                {
                    for(int t:v[j])
                    {
                        if(visit3[lo[t]]==0)
                        {
                            visit3[lo[t]]=1;
                            uoin(j,lo[t]);

                        }
                    }
                }
                 for(int j:w[i])
                {   visit3[j]=0;
                    for(int t:v[j])
                    {
                        if(visit3[lo[t]]==1)
                        {
                            visit3[lo[t]]=0;
                        }
                    }
                }

            }
              cout<<ans;
        }


// be name khoda
// never give up :))))
#include <bits/stdc++.h>
#define mp make_pair
#define f1 first
#define f2 second
#define int long long int
#define pb push_back
#define pii pair<ll ,ll>
#define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int mox=1e5+9;
vector <int> v[mox];
bool visit[mox];
bool ed[mox];
bool visit2[mox];
bool visit3[mox];
bool visit4[mox];
int u=0;
int p=0;
stack <int> s;
vector <int> w[mox];
int l=0;
vector <int> va[mox];
int lo[mox];
vector <int> ah;
bool visit5[mox];
void dfs(int x)
{
    visit[x]=1;
    for(int i:v[x])
    {
        if(visit[i]==0)
        {
            dfs(i);
        }
    }
    s.push(x);
}
void dfs2(int x)
{
    visit2[x]=1;
    u+=1;
    for(int i:v[x])
    {
        if(visit2[i]==0)
        {
            dfs2(i);
        }
        else if(ed[i]==0)
        {
            p=1;
        }
    }
    ed[x]=1;
    w[l].pb(x);
    lo[x]=l;
}
void dfs3(int x)
{
    visit4[x]=1;
    u+=1;
    ah.pb(x);
    visit5[x]=1;
    for(int i:va[x])
    {
        if(visit4[i]==0&&ed[i]==0)
        {
            dfs3(i);
        }
        else if(ed[i]==1&&visit4[i]==0)
        {
            u+=1;
          visit4[i]=1;
          ah.pb(i);
        }
    }
    ed[x]=1;
}
main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0 ; i<m ; i++)
    {
        int a,b;
        cin>>a>>b;
        v[a].pb(b);
    }
    int ans=0;
    for(int i=1 ; i<=n ; i++)
    {
        if(visit[i]==0)
        {
            dfs(i);
        }
    }
    while(s.empty()==0)
    {
        int v=s.top();
        s.pop();
        if(visit2[v]==0)
        {
            dfs2(v);
            if(p==1)
            ans+=1;
            p=0;
            ans+=u-1;
            u=0;
            l+=1;
        }
    }
    for(int i=l-1 ; i>=0 ; i--)
    {
        for(int j:w[i])
        {
            for(int t:v[j])
            {
                if(visit3[lo[t]]==0)
                {
                    visit3[lo[t]]=1;
                    va[i].pb(lo[t]);
                }
            }
        }
         for(int j:w[i])
        {
            for(int t:v[j])
            {
                if(visit3[lo[t]]==1)
                {
                    visit3[lo[t]]=0;
                }
            }
        }
    }
     for(int i=l-1 ; i>=0 ; i--)
    {
        if(visit5[i]==0)
        {
            dfs3(i);
            ans+=u-1;
            u=0;
            for(int j:ah)
                visit4[j]=0;
        }
    }
    cout<<ans;
}


    // be name khoda
    // never give up :))))
    #include <bits/stdc++.h>
    #define mp make_pair
    #define f1 first
    #define f2 second
    #define int long long int
    #define pb push_back
    #define pii pair<ll ,ll>
    #define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    using namespace std;
    const int mox=1e5+9;
    vector <int> vr[mox],vb[mox];
    bool visit[mox],visit2[mox];
    stack <int> s;
    int u=0;
    void dfs(int x)
    {
       visit[x]=1;
       u+=1;
       for(int i:vr[x])
       {
           if(visit[i]==0)
            dfs(i);
       }
       s.push(x);
    }
    void dfs2(int x)
    {
        visit2[x]=1;
        u+=1;
        for(int i:vb[x])
        {
            if(visit2[i]==0)
                dfs2(i);
        }
    }
    main()
    {
        int n,m;
        cin>>n>>m;
        for(int i=0 ; i<m ; i++)
        {
            int a,b;
            cin>>a>>b;
            vr[a].pb(b);
            vb[b].pb(a);
        }
        int ans=0;
        for(int i=1 ; i<=n ; i++)
        {
            if(visit[i]==0)
            {
                dfs(i);
                ans+=u-1;
                u=0;
            }
        }
        while(s.empty()==0)
        {
            int v=s.top();
            s.pop();
            if(visit2[v]==0)
            {
                dfs2(v);
                ans+=u-1;
                u=0;
            }
        }
        cout<<ans;

    }


// be name khoda
// never give up :))))
#include <bits/stdc++.h>
#define mp make_pair
#define f1 first
#define f2 second
#define int long long int
#define pb push_back
#define pii pair<ll ,ll>
#define ios  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int mox=1e5+9;
vector <int> v[mox];
bool visit[mox];
bool ed[mox];
bool visit2[mox];
bool visit3[mox];
bool visit4[mox];
int u=0;
int p=0;
stack <int> s;
vector <int> w[mox];
int l=0;
vector <int> va[mox];
int lo[mox];
bool ed2[mox];
bool visit5[mox];
void dfs(int x)
{
    visit[x]=1;
    for(int i:v[x])
    {
        if(visit[i]==0)
        {
            dfs(i);
        }
    }
    s.push(x);
}
void dfs2(int x)
{
    visit2[x]=1;
    u+=1;
    for(int i:v[x])
    {
        if(visit2[i]==0)
        {
            dfs2(i);
        }
        else if(ed[i]==0)
        {
            p=1;
        }
    }
    ed[x]=1;
    w[l].pb(x);
    lo[x]=l;
}
void dfs3(int x)
{
    visit4[x]=1;
    u+=1;
    for(int i:va[x])
    {
        if(visit4[i]==0&&ed[i]==0)
        {
            dfs3(i);
        }
        else if(ed[x]==1&&visit4[i]==0)
        {
            u+=1;
          visit4[i]=1;
        }
    }
    ed[x]=1;
}
void dfs4(int x)
{
    visit5[x]=1;
    for(int i:va[x])
    {
        if(visit5[i]==0)
        {
            dfs4(i);
        }
        visit4[i]=0;
    }
    visit5[x]=0;
}
main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0 ; i<m ; i++)
    {
        int a,b;
        cin>>a>>b;
        v[a].pb(b);
    }
    int ans=0;
    for(int i=1 ; i<=n ; i++)
    {
        if(visit[i]==0)
        {
            dfs(i);
        }
    }
    while(s.empty()==0)
    {
        int v=s.top();
        s.pop();
        if(visit2[v]==0)
        {
            dfs2(v);
            if(p==1)
            ans+=1;
            p=0;
            ans+=u-1;
            u=0;
            l+=1;
        }
    }
    for(int i=l-1 ; i>=0 ; i--)
    {
        for(int j:w[i])
        {
            for(int t:v[j])
            {
                if(visit3[lo[t]]==0)
                {
                    visit3[lo[t]]=1;
                    va[i].pb(lo[t]);
                }
            }
        }
         for(int j:w[i])
        {
            for(int t:v[j])
            {
                if(visit3[lo[t]]==1)
                {
                    visit3[lo[t]]=0;
                }
            }
        }
    }
     for(int i=l-1 ; i>=0 ; i--)
    {
        if(visit4[i]==0)
        {
            dfs3(i);
            ans+=u-1;
            u=0;
            dfs4(i);
        }
    }
    cout<<ans;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int  ,int > pii;
typedef pair<ll  ,ll > pll;

const ll maxn =2e6;
const ll mod = 1e9+7;
const ld PI = 4 * atan((ld) 1);

#define pb(x) push_back(x);
#define endl '\n'
#define dokme(x) cout << x ;  return(0);
#define migmig ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define file_init freopen("input.txt", "r+", stdin); freopen("output.txt", "w+", stdout);
#define ms(x , y) memset(x , y , sizeof x);
ll pw(ll a, ll b) {
    return (!b ? 1 : (b & 1 ? a * pw(a * a % mod, b / 2) % mod : pw(a * a % mod, b / 2) % mod));
}

int n , m;
vector < int > adj[maxn] , radj[maxn] , vec [maxn] , vc;
ll ans = 0;
bool done[maxn] , mark[maxn];
int color[maxn];
bool f = 0;

void findcomp(int v){
    done[v] = 1;
    for (auto u : vec[v]){
        if(!done[u]){
            findcomp(u);
        }
    }
    vc.pb(v);
}

int sfd(int v){
    mark[v] = 1;
    int ans = 1;
    for (auto u : radj[v]){
        if(!mark[u]){
            ans+=sfd(u);
        }
    }
    return(ans);
}

void solve(int s){
    done[s] = 1;
    vc.clear();
    findcomp(s);
    ans+=vc.size()-1;
    //if scc > 1 --> ans++;
    reverse(vc.begin() , vc.end());
    for (int i = 0 ; i < vc.size() ; i ++){
        if(!mark[vc[i]]){
            f|=(sfd(vc[i])>1);
        }
    }
}

int main(){
    migmig
    cin >> n >> m;ans = 0;
    for (int i = 0 ; i < m ; i ++){
        int u , v;
        cin >> u >> v;
        adj[u].pb(v);
        radj[v].pb(u);
        vec[u].pb(v) ; vec[v].pb(u);
    }
    for (int i = 1 ; i <= n ; i ++){
        if(!done[i]){
            solve(i);
        }
    }
    if(f)ans++;
    cout << ans;

    return(0);
}

//When we hit our lowest point, we are open to the greatest change.
//If I try, I fail. If I don't try, I'm NEVER GOING TO GET IT.
//Sometimes, life is like this dark tunnel. You can't always see the light at the end of the tunnel. But if you just keep moving... you will come to a better place.
//It is important to draw wisdom from diffrent places. If you take it from only one place it becomes rigid and stale.


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int  ,int > pii;
typedef pair<ll  ,ll > pll;

const ll maxn =2e5;
const ll mod = 1e9+7;
const ld PI = 4 * atan((ld) 1);

#define pb(x) push_back(x);
#define endl '\n'
#define dokme(x) cout << x ;  return(0);
#define migmig ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define file_init freopen("input.txt", "r+", stdin); freopen("output.txt", "w+", stdout);
#define ms(x , y) memset(x , y , sizeof x);
ll pw(ll a, ll b) {
    return (!b ? 1 : (b & 1 ? a * pw(a * a % mod, b / 2) % mod : pw(a * a % mod, b / 2) % mod));
}

int n , m;
ll ans = 0;
vector < int > adj[maxn] , radj[maxn] , vec[maxn] , vc , order;
bool mark[maxn] , done[maxn];

void find(int v){
    done[v] = 1;
    vc.pb(v);
    for (auto u : vec[v]){
        if(!done[u]){
            find(u);
        }
    }
}

void dfs(int v){
    mark[v] = 1;
    for (auto u : adj[v]){
        if(!mark[u]){
            dfs(u);
        }
    }
    order.pb(v);
}

void sfd(int v){
    mark[v] = 1;
    for (auto u : radj[v]){
        if(!mark[u]){
            sfd(u);
        }
    }
}

void solve(int v){
    done[v] = 1;
    ms(mark , 0);
    vc.clear();
    find(v);
    ms(mark , 0);
    for (int u : vc){
        if(!mark[u]){
            dfs(u);
        }
    }
    reverse(order.begin() , order.end());
    ms(mark , 0);
    int scc = 0;
    for (auto u : order){
        if(!mark[u]){
            sfd(u);
            scc++;
        }
    }
    ans+=order.size() - (scc == order.size());
}

int main(){
    migmig
    cin >> n >> m;ans = 0;
    for (int i = 0 ; i < m ; i ++){
        int u , v;
        cin >> u >> v;
        adj[u].pb(v);
        radj[v].pb(u);
        vec[u].pb(v) ; vec[v].pb(u);
    }
    for (int i = 1 ; i <= n ; i ++){
        if(!done[i]){
            solve(i);
        }
    }
    dokme(ans);
    return(0);
}

//When we hit our lowest point, we are open to the greatest change.
//If I try, I fail. If I don't try, I'm NEVER GOING TO GET IT.
//Sometimes, life is like this dark tunnel. You can't always see the light at the end of the tunnel. But if you just keep moving... you will come to a better place.
//It is important to draw wisdom from diffrent places. If you take it from only one place it becomes rigid and stale.


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int  ,int > pii;
typedef pair<ll  ,ll > pll;

const ll maxn =2e5;
const ll mod = 1e9+7;
const ld PI = 4 * atan((ld) 1);

#define pb(x) push_back(x);
#define endl '\n'
#define dokme(x) cout << x ;  return(0);
#define migmig ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define file_init freopen("input.txt", "r+", stdin); freopen("output.txt", "w+", stdout);
#define ms(x , y) memset(x , y , sizeof x);
ll pw(ll a, ll b) {
    return (!b ? 1 : (b & 1 ? a * pw(a * a % mod, b / 2) % mod : pw(a * a % mod, b / 2) % mod));
}

int n , m;
ll ans = 0;
vector < int > adj[maxn] , radj[maxn] , vec[maxn] , vc , order;
bool mark[maxn] , done[maxn];

void find(int v){
    done[v] = 1;
    vc.pb(v);
    for (auto u : vec[v]){
        if(!done[u]){
            find(u);
        }
    }
}

void dfs(int v){
    mark[v] = 1;
    for (auto u : adj[v]){
        if(!mark[u]){
            dfs(u);
        }
    }
    order.pb(v);
}

void sfd(int v){
    mark[v] = 1;
    for (auto u : radj[v]){
        if(!mark[u]){
            sfd(u);
        }
    }
}

void solve(int v){
    done[v] = 1;
    ms(mark , 0);
    vc.clear();
    find(v);
    ms(mark , 0);
    order.clear();
    for (int u : vc){
        if(!mark[u]){
            dfs(u);
        }
    }
    reverse(order.begin() , order.end());
    ms(mark , 0);
    int scc = 0;
    for (auto u : order){
        if(!mark[u]){
            sfd(u);
            scc++;
        }
    }
    ans+=order.size() - (scc == order.size());
}

int main(){
    migmig
    cin >> n >> m;ans = 0;
    for (int i = 0 ; i < m ; i ++){
        int u , v;
        cin >> u >> v;
        adj[u].pb(v);
        radj[v].pb(u);
        vec[u].pb(v) ; vec[v].pb(u);
    }
    for (int i = 1 ; i <= n ; i ++){
        if(!done[i]){
            solve(i);
        }
    }
    dokme(ans);
    return(0);
}

//When we hit our lowest point, we are open to the greatest change.
//If I try, I fail. If I don't try, I'm NEVER GOING TO GET IT.
//Sometimes, life is like this dark tunnel. You can't always see the light at the end of the tunnel. But if you just keep moving... you will come to a better place.
//It is important to draw wisdom from diffrent places. If you take it from only one place it becomes rigid and stale.


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int  ,int > pii;
typedef pair<ll  ,ll > pll;

const ll maxn =2e5;
const ll mod = 1e9+7;
const ld PI = 4 * atan((ld) 1);

#define pb(x) push_back(x);
#define endl '\n'
#define dokme(x) cout << x ;  return(0);
#define migmig ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define file_init freopen("input.txt", "r+", stdin); freopen("output.txt", "w+", stdout);
#define ms(x , y) memset(x , y , sizeof x);
ll pw(ll a, ll b) {
    return (!b ? 1 : (b & 1 ? a * pw(a * a % mod, b / 2) % mod : pw(a * a % mod, b / 2) % mod));
}

int n , m;
ll ans = 0;
vector < int > adj[maxn] , radj[maxn] , vec[maxn] , vc , order;
bool mark[maxn] , done[maxn];

void find(int v){
    done[v] = 1;
    vc.pb(v);
    for (auto u : vec[v]){
        if(!done[u]){
            find(u);
        }
    }
}

void dfs(int v){
    mark[v] = 1;
    for (auto u : adj[v]){
        if(!mark[u]){
            dfs(u);
        }
    }
    order.pb(v);
}

void sfd(int v){
    mark[v] = 1;
    for (auto u : radj[v]){
        if(!mark[u]){
            sfd(u);
        }
    }
}

void solve(int v){
    done[v] = 1;
    //ms(mark , 0);
    vc.clear();
    find(v);
    //ms(mark , 0);
    order.clear();
    for (int u : vc){
        if(!mark[u]){
            dfs(u);
        }
    }
    reverse(order.begin() , order.end());
    //ms(mark , 0);
    int scc = 0;
    for (auto u : order){
        if(!mark[u]){
            sfd(u);
            scc++;
        }
    }
    ans+=order.size() - (scc == order.size());
}

int main(){
    migmig
    cin >> n >> m;ans = 0;
    for (int i = 0 ; i < m ; i ++){
        int u , v;
        cin >> u >> v;
        adj[u].pb(v);
        radj[v].pb(u);
        vec[u].pb(v) ; vec[v].pb(u);
    }
    for (int i = 1 ; i <= n ; i ++){
        if(!done[i]){
            solve(i);
        }
    }
    dokme(ans);
    return(0);
}

//When we hit our lowest point, we are open to the greatest change.
//If I try, I fail. If I don't try, I'm NEVER GOING TO GET IT.
//Sometimes, life is like this dark tunnel. You can't always see the light at the end of the tunnel. But if you just keep moving... you will come to a better place.
//It is important to draw wisdom from diffrent places. If you take it from only one place it becomes rigid and stale.


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int  ,int > pii;
typedef pair<ll  ,ll > pll;

const ll maxn =2e5;
const ll mod = 1e9+7;
const ld PI = 4 * atan((ld) 1);

#define pb(x) push_back(x);
#define endl '\n'
#define dokme(x) cout << x ;  return(0);
#define migmig ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define file_init freopen("input.txt", "r+", stdin); freopen("output.txt", "w+", stdout);
#define ms(x , y) memset(x , y , sizeof x);
ll pw(ll a, ll b) {
    return (!b ? 1 : (b & 1 ? a * pw(a * a % mod, b / 2) % mod : pw(a * a % mod, b / 2) % mod));
}

int n , m;
ll ans = 0;
vector < int > adj[maxn] , radj[maxn] , vec[maxn] , vc , order;
bool mark[maxn] , done[maxn];

void find(int v){
    done[v] = 1;
    vc.pb(v);
    for (auto u : vec[v]){
        if(!done[u]){
            find(u);
        }
    }
}

void dfs(int v){
    mark[v] = 1;
    for (auto u : adj[v]){
        if(!mark[u]){
            dfs(u);
        }
    }
    order.pb(v);
}

void sfd(int v){
    mark[v] = 1;
    for (auto u : radj[v]){
        if(!mark[u]){
            sfd(u);
        }
    }
}

void solve(int v){
    done[v] = 1;
    //ms(mark , 0);
    vc.clear();
    find(v);
    //ms(mark , 0);
    order.clear();
    for (int u : vc){
        if(!mark[u]){
            dfs(u);
        }
    }
    reverse(order.begin() , order.end());
    ms(mark , 0);
    int scc = 0;
    for (auto u : order){
        if(!mark[u]){
            sfd(u);
            scc++;
        }
    }
    ans+=order.size() - (scc == order.size());
}

int main(){
    migmig
    cin >> n >> m;ans = 0;
    for (int i = 0 ; i < m ; i ++){
        int u , v;
        cin >> u >> v;
        adj[u].pb(v);
        radj[v].pb(u);
        vec[u].pb(v) ; vec[v].pb(u);
    }
    for (int i = 1 ; i <= n ; i ++){
        if(!done[i]){
            solve(i);
        }
    }
    dokme(ans);
    return(0);
}

//When we hit our lowest point, we are open to the greatest change.
//If I try, I fail. If I don't try, I'm NEVER GOING TO GET IT.
//Sometimes, life is like this dark tunnel. You can't always see the light at the end of the tunnel. But if you just keep moving... you will come to a better place.
//It is important to draw wisdom from diffrent places. If you take it from only one place it becomes rigid and stale.


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int  ,int > pii;
typedef pair<ll  ,ll > pll;

const ll maxn =2e6;
const ll mod = 1e9+7;
const ld PI = 4 * atan((ld) 1);

#define pb(x) push_back(x);
#define endl '\n'
#define dokme(x) cout << x ;  return(0);
#define migmig ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define file_init freopen("input.txt", "r+", stdin); freopen("output.txt", "w+", stdout);
#define ms(x , y) memset(x , y , sizeof x);
ll pw(ll a, ll b) {
    return (!b ? 1 : (b & 1 ? a * pw(a * a % mod, b / 2) % mod : pw(a * a % mod, b / 2) % mod));
}

int n , m;
vector < int > adj[maxn] , radj[maxn] , vec [maxn] , vc;
ll ans = 0;
bool done[maxn] , mark[maxn];
int color[maxn];

void findcomp(int v){
    done[v] = 1;
    for (auto u : vec[v]){
        if(!done[u]){
            findcomp(u);
        }
    }
    vc.pb(v);
}

bool sfd(int v){
    mark[v] = 1;
    for (auto u : radj[v]){
        if(!mark[u]){
            return(1);
        }
    }
    return(0);
}

void solve(int s){
    done[s] = 1;
    vc.clear();
    findcomp(s);
    ans+=vc.size()-1;
    //if scc > 1 --> ans++;
    reverse(vc.begin() , vc.end());
    for (int i = 0 ; i < vc.size() ; i ++){
        if(!mark[vc[i]]){
            bool f = sfd(vc[i]);
            if(f){
                ans++;
                break;
            }
        }
    }
}

int main(){
    migmig
    cin >> n >> m;ans = 0;
    for (int i = 0 ; i < m ; i ++){
        int u , v;
        cin >> u >> v;
        adj[u].pb(v);
        radj[v].pb(u);
        vec[u].pb(v) ; vec[v].pb(u);
    }
    for (int i = 1 ; i <= n ; i ++){
        if(!done[i]){
            solve(i);
        }
    }
    cout << ans;

    return(0);
}

//When we hit our lowest point, we are open to the greatest change.
//If I try, I fail. If I don't try, I'm NEVER GOING TO GET IT.
//Sometimes, life is like this dark tunnel. You can't always see the light at the end of the tunnel. But if you just keep moving... you will come to a better place.
//It is important to draw wisdom from diffrent places. If you take it from only one place it becomes rigid and stale.


#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define gc getchar()
#define pc(x) putchar(x)
template<typename T> void scan(T &x){x = 0;bool _=0;T c=gc;_=c==45;c=_?gc:c;while(c<48||c>57)c=gc;for(;c<48||c>57;c=gc);for(;c>47&&c<58;c=gc)x=(x<<3)+(x<<1)+(c&15);x=_?-x:x;}
template<typename T> void printn(T n){bool _=0;_=n<0;n=_?-n:n;char snum[65];int i=0;do{snum[i++]=n%10+48;n/= 10;}while(n);--i;if (_)pc(45);while(i>=0)pc(snum[i--]);}
template<typename First, typename ... Ints> void scan(First &arg, Ints&... rest){scan(arg);scan(rest...);}
template<typename T> void print(T n){printn(n);pc(10);}
template<typename First, typename ... Ints> void print(First arg, Ints... rest){printn(arg);pc(32);print(rest...);}

using namespace std;
const int MM = 2e5+5;

int n, m, dfn[MM], low[MM], t, path[MM], ptr, id[MM], sz[MM];
bool ins[MM];
vector<int> adj[MM];
set<int> adj2[MM];

void dfs(int cur){
	ins[cur] = 1;
	path[++ptr] = cur;
	dfn[cur] = low[cur] = ++t;

	for(int u: adj[cur]){
		if(!dfn[u]){
			dfs(u);
			low[cur] = min(low[cur], low[u]);
		}
		else if(ins[u])
			low[cur] = min(low[cur], dfn[u]);
	}
	if(dfn[cur] == low[cur]){
		int u = 0;
		do{
			u = path[ptr--];
			ins[u] = 0;
			id[u] = cur;
			sz[cur]++;
		} while(u != cur);
	}
}
int ans, par[MM], sz2[MM];
int cyc[MM];

int find(int x){
	while(x != par[x])
		x = par[x], par[x] = par[par[x]];
	return x;
}

int va[MM], vb[MM];

int main(){
	scan(n, m);
	for(int i = 1; i <= n; i++){
		par[i] = i;
		sz2[i] = 1;
	}
	for(int i = 0,a,b; i < m; i++){
		scan(a, b);
		adj[a].emplace_back(b);
		va[i] = a, vb[i] = b;
		a = find(a), b = find(b);
		if(a != b){
			par[a] = b;
			sz2[a] += sz2[b];
		}
	}
	for(int i = 1; i <= n; i++){
		if(!dfn[i])
			dfs(i);
	}
	for(int i = 0,a,b; i < m; i++){
		a = id[va[i]], b = id[vb[i]];
		assert(a and b);
		if(a != b){
			adj2[a].insert(b);
		}
	}

	for(int i = 1; i <= n; i++){
		// print(i, id[i], sz[i]);
		ans += sz2[i]-1;
		if(sz[i] > 1){
			if(!cyc[find(i)]){
				ans++;
				cyc[find(i)] = 1;
			}
		}
	}

	print(ans);
}


#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define gc getchar()
#define pc(x) putchar(x)
template<typename T> void scan(T &x){x = 0;bool _=0;T c=gc;_=c==45;c=_?gc:c;while(c<48||c>57)c=gc;for(;c<48||c>57;c=gc);for(;c>47&&c<58;c=gc)x=(x<<3)+(x<<1)+(c&15);x=_?-x:x;}
template<typename T> void printn(T n){bool _=0;_=n<0;n=_?-n:n;char snum[65];int i=0;do{snum[i++]=n%10+48;n/= 10;}while(n);--i;if (_)pc(45);while(i>=0)pc(snum[i--]);}
template<typename First, typename ... Ints> void scan(First &arg, Ints&... rest){scan(arg);scan(rest...);}
template<typename T> void print(T n){printn(n);pc(10);}
template<typename First, typename ... Ints> void print(First arg, Ints... rest){printn(arg);pc(32);print(rest...);}

using namespace std;
const int MM = 2e5+5;

int n, m, dfn[MM], low[MM], t, path[MM], ptr, id[MM], sz[MM];
bool ins[MM];
vector<int> adj[MM];
set<int> adj2[MM];

void dfs(int cur, int pre){
	ins[cur] = 1;
	path[++ptr] = cur;
	dfn[cur] = low[cur] = ++t;

	for(int u: adj[cur]){
		if(!dfn[u]){
			dfs(u, cur);
			low[cur] = min(low[cur], low[u]);
		}
		else if(ins[u])
			low[cur] = min(low[cur], dfn[u]);
	}
	if(dfn[cur] == low[cur]){
		int u = 0;
		do{
			u = path[ptr--];
			ins[u] = 0;
			id[u] = cur;
			sz[cur]++;
		} while(u != cur);
	}
}
int ans, par[MM];
bool vis[MM];

int find(int x){
	while(x != par[x])
		x = par[x], par[x] = par[par[x]];
	return x;
}

void go(int cur){
	vis[cur] = 1;
	for(int u: adj2[cur]){
		int a = find(cur), b = find(u);
		if(a != b){
			par[a] = b;
			ans++;
			go(u);
		}
	}
}

int va[MM], vb[MM];

int main(){
	scan(n, m);
	for(int i = 0,a,b; i < m; i++){
		scan(a, b);
		adj[a].emplace_back(b);
		va[i] = a, vb[i] = b;
	}
	for(int i = 1; i <= n; i++){
		if(!dfn[i])
			dfs(i, 0);
	}
	for(int i = 0,a,b; i < m; i++){
		a = id[va[i]], b = id[vb[i]];
		if(a != b){
			adj2[a].insert(b);
		}
	}

	for(int i = 1; i <= n; i++){
		par[i] = i;
		// print(i, id[i], sz[i]);
		if(sz[i] > 1)
			ans += sz[i]; //scc cost
	}

	for(int i = 1; i <= n; i++){
		if(!vis[i])
			go(i);
	}

	print(ans);
}


#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define gc getchar()
#define pc(x) putchar(x)
template<typename T> void scan(T &x){x = 0;bool _=0;T c=gc;_=c==45;c=_?gc:c;while(c<48||c>57)c=gc;for(;c<48||c>57;c=gc);for(;c>47&&c<58;c=gc)x=(x<<3)+(x<<1)+(c&15);x=_?-x:x;}
template<typename T> void printn(T n){bool _=0;_=n<0;n=_?-n:n;char snum[65];int i=0;do{snum[i++]=n%10+48;n/= 10;}while(n);--i;if (_)pc(45);while(i>=0)pc(snum[i--]);}
template<typename First, typename ... Ints> void scan(First &arg, Ints&... rest){scan(arg);scan(rest...);}
template<typename T> void print(T n){printn(n);pc(10);}
template<typename First, typename ... Ints> void print(First arg, Ints... rest){printn(arg);pc(32);print(rest...);}

using namespace std;
const int MM = 2e5+5;

int n, m, dfn[MM], low[MM], t, path[MM], ptr, id[MM], sz[MM];
bool ins[MM];
vector<int> adj[MM];
set<int> adj2[MM];

void dfs(int cur, int pre){
	ins[cur] = 1;
	path[++ptr] = cur;
	dfn[cur] = low[cur] = ++t;

	for(int u: adj[cur]){
		if(!dfn[u]){
			dfs(u, cur);
			low[cur] = min(low[cur], low[u]);
		}
		else if(ins[u])
			low[cur] = min(low[cur], dfn[u]);
	}
	if(dfn[cur] == low[cur]){
		int u = 0;
		do{
			u = path[ptr--];
			ins[u] = 0;
			id[u] = cur;
			sz[cur]++;
		} while(u != cur);
	}
}
int ans, par[MM];
bool vis[MM];

int find(int x){
	while(x != par[x])
		x = par[x], par[x] = par[par[x]];
	return x;
}

void go(int cur){
	vis[cur] = 1;
	for(int u: adj2[cur]){
		int a = find(cur), b = find(u);
		if(a != b){
			par[a] = b;
			ans++;
			go(u);
		}
	}
}

int va[MM], vb[MM];

int main(){
	scan(n, m);
	for(int i = 0,a,b; i < m; i++){
		scan(a, b);
		adj[a].emplace_back(b);
		va[i] = a, vb[i] = b;
	}
	for(int i = 1; i <= n; i++){
		if(!dfn[i])
			dfs(i, 0);
	}
	for(int i = 0,a,b; i < m; i++){
		a = id[va[i]], b = id[vb[i]];
		if(a != b){
			adj2[a].insert(b);
		}
	}

	for(int i = 1; i <= n; i++){
		par[i] = i;
		// print(i, id[i], sz[i]);
		if(sz[i] > 1)
			ans += sz[i]; //scc cost
	}

	for(int i = 1; i <= n; i++){
		go(i);
	}

	print(ans);
}


#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define gc getchar()
#define pc(x) putchar(x)
template<typename T> void scan(T &x){x = 0;bool _=0;T c=gc;_=c==45;c=_?gc:c;while(c<48||c>57)c=gc;for(;c<48||c>57;c=gc);for(;c>47&&c<58;c=gc)x=(x<<3)+(x<<1)+(c&15);x=_?-x:x;}
template<typename T> void printn(T n){bool _=0;_=n<0;n=_?-n:n;char snum[65];int i=0;do{snum[i++]=n%10+48;n/= 10;}while(n);--i;if (_)pc(45);while(i>=0)pc(snum[i--]);}
template<typename First, typename ... Ints> void scan(First &arg, Ints&... rest){scan(arg);scan(rest...);}
template<typename T> void print(T n){printn(n);pc(10);}
template<typename First, typename ... Ints> void print(First arg, Ints... rest){printn(arg);pc(32);print(rest...);}

using namespace std;
const int MM = 1e5+1;

int n, m, dfn[MM], low[MM], t, path[MM], ptr, id[MM], sz[MM];
bool ins[MM];
vector<int> adj[MM];
set<int> adj2[MM];

void dfs(int cur, int pre){
	ins[cur] = 1;
	path[++ptr] = cur;
	dfn[cur] = low[cur] = ++t;

	for(int u: adj[cur]){
		if(!dfn[u]){
			dfs(u, cur);
			low[cur] = min(low[cur], low[u]);
		}
		else if(ins[u])
			low[cur] = min(low[cur], dfn[u]);
	}
	if(dfn[cur] == low[cur]){
		int u = cur;
		do{
			id[u] = cur;
			sz[cur]++;
			u = path[ptr--];
			ins[u] = 0;
		} while(u != cur);
	}
}
int ans, par[MM];
bool vis[MM];

int find(int x){
	while(x != par[x])
		x = par[x], par[x] = par[par[x]];
	return x;
}

void go(int cur){
	vis[cur] = 1;
	for(int u: adj2[cur]){
		int a = find(cur), b = find(u);
		if(a != b){
			par[a] = b;
			ans++;
			go(u);
		}
	}
}

int va[MM], vb[MM];

int main(){
	scan(n, m);
	for(int i = 0,a,b; i < m; i++){
		scan(a, b);
		adj[a].emplace_back(b);
		va[i] = a, vb[i] = b;
	}
	for(int i = 1; i <= n; i++){
		if(!dfn[i])
			dfs(i, 0);
	}
	for(int i = 0,a,b; i < m; i++){
		a = id[va[i]], b = id[vb[i]];
		if(a != b){
			adj2[a].insert(b);
		}
	}

	for(int i = 1; i <= n; i++){
		par[i] = i;
		// print(i, id[i], sz[i]);
		if(sz[i] > 1)
			ans += sz[i]; //scc cost
	}

	for(int i = 1; i <= n; i++){
		if(!vis[i])
			go(i);
	}

	print(ans);
}


#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define gc getchar()
#define pc(x) putchar(x)
template<typename T> void scan(T &x){x = 0;bool _=0;T c=gc;_=c==45;c=_?gc:c;while(c<48||c>57)c=gc;for(;c<48||c>57;c=gc);for(;c>47&&c<58;c=gc)x=(x<<3)+(x<<1)+(c&15);x=_?-x:x;}
template<typename T> void printn(T n){bool _=0;_=n<0;n=_?-n:n;char snum[65];int i=0;do{snum[i++]=n%10+48;n/= 10;}while(n);--i;if (_)pc(45);while(i>=0)pc(snum[i--]);}
template<typename First, typename ... Ints> void scan(First &arg, Ints&... rest){scan(arg);scan(rest...);}
template<typename T> void print(T n){printn(n);pc(10);}
template<typename First, typename ... Ints> void print(First arg, Ints... rest){printn(arg);pc(32);print(rest...);}

using namespace std;
const int MM = 1e5+5;

int n, m, dfn[MM], low[MM], t, path[MM], ptr, id[MM], sz[MM];
bool ins[MM];
vector<int> adj[MM];
set<int> adj2[MM];

void dfs(int cur, int pre){
	ins[cur] = 1;
	path[++ptr] = cur;
	dfn[cur] = low[cur] = ++t;

	for(int u: adj[cur]){
		if(!dfn[u]){
			dfs(u, cur);
			low[cur] = min(low[cur], low[u]);
		}
		else if(ins[u])
			low[cur] = min(low[cur], dfn[u]);
	}
	if(dfn[cur] == low[cur]){
		int u = cur;
		do{
			id[u] = cur;
			sz[cur]++;
			u = path[ptr--];
			ins[u] = 0;
		} while(u != cur);
	}
}
int ans, par[MM];
bool vis[MM];

int find(int x){
	while(x != par[x])
		x = par[x], par[x] = par[par[x]];
	return x;
}

void go(int cur){
	vis[cur] = 1;
	for(int u: adj2[cur]){
		int a = find(cur), b = find(u);
		if(a != b){
			par[a] = b;
			ans++;
			go(u);
		}
	}
}

int va[MM], vb[MM];

int main(){
	scan(n, m);
	for(int i = 0,a,b; i < m; i++){
		scan(a, b);
		adj[a].emplace_back(b);
		va[i] = a, vb[i] = b;
	}
	for(int i = 1; i <= n; i++){
		if(!dfn[i])
			dfs(i, 0);
	}
	for(int i = 0,a,b; i < m; i++){
		a = id[va[i]], b = id[vb[i]];
		if(a != b){
			adj2[a].insert(b);
		}
	}
	int sum = 0;
	for(int i = 1; i <= n; i++){
		par[i] = i;
		// print(i, id[i], sz[i]);
		sum += sz[i];
		if(sz[i] > 1)
			ans += sz[i]; //scc cost
	}
	assert(sum == n);

	for(int i = 1; i <= n; i++){
		if(!vis[i])
			go(i);
	}

	print(ans);
}


#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define gc getchar()
#define pc(x) putchar(x)
template<typename T> void scan(T &x){x = 0;bool _=0;T c=gc;_=c==45;c=_?gc:c;while(c<48||c>57)c=gc;for(;c<48||c>57;c=gc);for(;c>47&&c<58;c=gc)x=(x<<3)+(x<<1)+(c&15);x=_?-x:x;}
template<typename T> void printn(T n){bool _=0;_=n<0;n=_?-n:n;char snum[65];int i=0;do{snum[i++]=n%10+48;n/= 10;}while(n);--i;if (_)pc(45);while(i>=0)pc(snum[i--]);}
template<typename First, typename ... Ints> void scan(First &arg, Ints&... rest){scan(arg);scan(rest...);}
template<typename T> void print(T n){printn(n);pc(10);}
template<typename First, typename ... Ints> void print(First arg, Ints... rest){printn(arg);pc(32);print(rest...);}

using namespace std;
const int MM = 1e5+5;

int n, m, dfn[MM], low[MM], t, path[MM], ptr, id[MM], sz[MM];
bool ins[MM];
vector<int> adj[MM];
set<int> adj2[MM];

void dfs(int cur, int pre){
	ins[cur] = 1;
	path[++ptr] = cur;
	dfn[cur] = low[cur] = ++t;

	for(int u: adj[cur]){
		if(!dfn[u]){
			dfs(u, cur);
			low[cur] = min(low[cur], low[u]);
		}
		else if(ins[u])
			low[cur] = min(low[cur], dfn[u]);
	}
	if(dfn[cur] == low[cur]){
		int u = 0;
		do{
			u = path[ptr--];
			ins[u] = 0;
			id[u] = cur;
			sz[cur]++;
		} while(u != cur);
	}
}
int ans, par[MM];
bool vis[MM];

int find(int x){
	while(x != par[x])
		x = par[x], par[x] = par[par[x]];
	return x;
}

void go(int cur){
	vis[cur] = 1;
	for(int u: adj2[cur]){
		int a = find(cur), b = find(u);
		if(a != b){
			par[a] = b;
			ans++;
			go(u);
		}
	}
}

int va[MM], vb[MM];

int main(){
	scan(n, m);
	for(int i = 0,a,b; i < m; i++){
		scan(a, b);
		adj[a].emplace_back(b);
		va[i] = a, vb[i] = b;
	}
	for(int i = 1; i <= n; i++){
		if(!dfn[i])
			dfs(i, 0);
	}
	for(int i = 0,a,b; i < m; i++){
		a = id[va[i]], b = id[vb[i]];
		if(a != b){
			adj2[a].insert(b);
		}
	}

	for(int i = 1; i <= n; i++){
		par[i] = i;
		// print(i, id[i], sz[i]);
		if(sz[i] > 1)
			ans += sz[i]; //scc cost
	}

	for(int i = 1; i <= n; i++){
		if(!vis[i])
			go(i);
	}

	print(ans);
}


#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define gc getchar()
#define pc(x) putchar(x)
template<typename T> void scan(T &x){x = 0;bool _=0;T c=gc;_=c==45;c=_?gc:c;while(c<48||c>57)c=gc;for(;c<48||c>57;c=gc);for(;c>47&&c<58;c=gc)x=(x<<3)+(x<<1)+(c&15);x=_?-x:x;}
template<typename T> void printn(T n){bool _=0;_=n<0;n=_?-n:n;char snum[65];int i=0;do{snum[i++]=n%10+48;n/= 10;}while(n);--i;if (_)pc(45);while(i>=0)pc(snum[i--]);}
template<typename First, typename ... Ints> void scan(First &arg, Ints&... rest){scan(arg);scan(rest...);}
template<typename T> void print(T n){printn(n);pc(10);}
template<typename First, typename ... Ints> void print(First arg, Ints... rest){printn(arg);pc(32);print(rest...);}

using namespace std;
const int MM = 1e5+1;

int n, m, dfn[MM], low[MM], t, path[MM], ptr, id[MM], sz[MM];
bool ins[MM];
vector<int> adj[MM];
set<int> adj2[MM];

void dfs(int cur, int pre){
	ins[cur] = 1;
	path[++ptr] = cur;
	dfn[cur] = low[cur] = ++t;

	for(int u: adj[cur]){
		if(!dfn[u]){
			dfs(u, cur);
			low[cur] = min(low[cur], low[u]);
		}
		else if(ins[u])
			low[cur] = min(low[cur], dfn[u]);
	}
	if(dfn[cur] == low[cur]){
		int u = cur;
		do{
			id[u] = cur;
			sz[cur]++;
			u = path[ptr--];
			ins[u] = 0;
		} while(u != cur);
	}
}
int ans;
bool vis[MM];

void go(int cur){
	vis[cur] = 1;
	for(int u: adj2[cur]){
		if(!vis[u]){
			ans++;
			go(u);
		}
	}
}

int va[MM], vb[MM];

int main(){
	scan(n, m);
	for(int i = 0,a,b; i < m; i++){
		scan(a, b);
		adj[a].emplace_back(b);
		va[i] = a, vb[i] = b;
	}
	for(int i = 1; i <= n; i++){
		if(!dfn[i])
			dfs(i, 0);
	}
	for(int i = 0,a,b; i < m; i++){
		a = id[va[i]], b = id[vb[i]];
		if(a != b){
			adj2[a].insert(b);
		}
	}

	for(int i = 1; i <= n; i++){
		// print(i, id[i], sz[i]);
		if(sz[i] > 1)
			ans += sz[i]; //scc cost
	}

	for(int i = 1; i <= n; i++){
		if(!vis[i])
			go(i);
	}

	print(ans);
}


#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define gc getchar()
#define pc(x) putchar(x)
template<typename T> void scan(T &x){x = 0;bool _=0;T c=gc;_=c==45;c=_?gc:c;while(c<48||c>57)c=gc;for(;c<48||c>57;c=gc);for(;c>47&&c<58;c=gc)x=(x<<3)+(x<<1)+(c&15);x=_?-x:x;}
template<typename T> void printn(T n){bool _=0;_=n<0;n=_?-n:n;char snum[65];int i=0;do{snum[i++]=n%10+48;n/= 10;}while(n);--i;if (_)pc(45);while(i>=0)pc(snum[i--]);}
template<typename First, typename ... Ints> void scan(First &arg, Ints&... rest){scan(arg);scan(rest...);}
template<typename T> void print(T n){printn(n);pc(10);}
template<typename First, typename ... Ints> void print(First arg, Ints... rest){printn(arg);pc(32);print(rest...);}

using namespace std;
const int MM = 2e5+5;

int n, m, dfn[MM], low[MM], t, path[MM], ptr, id[MM], sz[MM];
bool ins[MM];
vector<int> adj[MM];
set<int> adj2[MM];

void dfs(int cur){
	ins[cur] = 1;
	path[++ptr] = cur;
	dfn[cur] = low[cur] = ++t;

	for(int u: adj[cur]){
		if(!dfn[u]){
			dfs(u);
			low[cur] = min(low[cur], low[u]);
		}
		else if(ins[u])
			low[cur] = min(low[cur], dfn[u]);
	}
	if(dfn[cur] == low[cur]){
		int u = 0;
		do{
			u = path[ptr--];
			ins[u] = 0;
			id[u] = cur;
			sz[cur]++;
		} while(u != cur);
	}
}
int ans, par[MM];
bool vis[MM];

int find(int x){
	while(x != par[x])
		x = par[x], par[x] = par[par[x]];
	return x;
}

void go(int cur){
	vis[cur] = 1;
	for(int u: adj2[cur]){
		int a = find(cur), b = find(u);
		if(a != b){
			par[a] = b;
			ans++;
			go(u);
		}
	}
}

int va[MM], vb[MM];

int main(){
	scan(n, m);
	for(int i = 0,a,b; i < m; i++){
		scan(a, b);
		adj[a].emplace_back(b);
		va[i] = a, vb[i] = b;
	}
	for(int i = 1; i <= n; i++){
		if(!dfn[i])
			dfs(i);
	}
	for(int i = 0,a,b; i < m; i++){
		a = id[va[i]], b = id[vb[i]];
		assert(a and b);
		if(a != b){
			adj2[a].insert(b);
		}
	}

	for(int i = 1; i <= n; i++){
		par[i] = i;
		// print(i, id[i], sz[i]);
		if(sz[i] > 1)
			ans += sz[i]; //scc cost
	}

	for(int i = 1; i <= n; i++){
		go(i);
	}

	print(ans);
}


#include<bits/stdc++.h>
inline int read(){
		int x=0,f=1;char ch=getchar();
		while(!isdigit(ch)){
			if(ch=='-') f=-1;ch=getchar();
		}
		while(isdigit(ch)){
			x=(x<<1)+(x<<3)+ch-48;
			ch=getchar();
		}
		return x*f;
	}
const int N=1e5+10;
int n,m,col[N],cnt;
bool flg[N],vis[N],isk[N];
std::vector<int>g[N],g1[N];
void dfs1(int u){col[u]=cnt;for(auto v:g1[u])if(!col[v])dfs1(v);}
void dfs(int u){if(vis[u]){flg[col[u]]|=isk[u];return;}vis[u]=isk[u]=1;for(auto v:g[u])dfs(v);isk[u]=0;}
int main()
{
	int i,x,y;
	n=read();m=read();
	for(i=1;i<=m;i++)x=read(),y=read(),g[x].push_back(y),
	g1[x].push_back(y),g1[y].push_back(x);
	for(i=1;i<=n;i++)if(!col[i])++cnt,dfs1(i);
	for(i=1;i<=n;i++)if(!vis[i])dfs(i);
	for(i=1,y=n-cnt;i<=cnt;i++)y+=flg[i];
	printf("%d\n",y);
	return 0;
}


#include<bits/stdc++.h>
int read(){
		int x=0,f=1;char ch=getchar();
		while(!isdigit(ch)){
			if(ch=='-') f=-1;ch=getchar();
		}
		while(isdigit(ch)){
			x=(x<<1)+(x<<3)+ch-48;
			ch=getchar();
		}
		return x*f;
	}
const int N=1e5+10;
int n,m,col[N],cnt;
int flg[N],vis[N],isk[N];
std::vector<int>g[N],g1[N];
void dfs1(int u){col[u]=cnt;for(auto v:g1[u])if(!col[v])dfs1(v);}
void dfs(int u){if(vis[u]){flg[col[u]]|=isk[u];return;}vis[u]=isk[u]=1;for(auto v:g[u])dfs(v);isk[u]=0;}
int main()
{
	int i,x,y;
	n=read();m=read();
	for(i=1;i<=m;i++)x=read(),y=read(),g[x].push_back(y),
	g1[x].push_back(y),g1[y].push_back(x);
	for(i=1;i<=n;i++)if(!col[i])++cnt,dfs1(i);
	for(i=1;i<=n;i++)if(!vis[i])dfs(i);
	for(i=1,y=n-cnt;i<=cnt;i++)y+=flg[i];
	printf("%d\n",y);
	return 0;
}


#include<bits/stdc++.h>
const int N=1e5+10;
int n,m,col[N],cnt;
bool flg[N],vis[N],isk[N];
std::vector<int>g[N],g1[N];
void dfs1(int u){col[u]=cnt;for(auto v:g1[u])if(!col[v])dfs1(v);}
void dfs(int u){if(vis[u]){flg[col[u]]|=isk[u];return;}vis[u]=isk[u]=1;for(auto v:g[u])dfs(v);isk[u]=0;}
int main()
{
	int i,x,y;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++)scanf("%d%d",&x,&y),g[x].push_back(y),
	g1[x].push_back(y),g1[y].push_back(x);
	for(i=1;i<=n;i++)if(!col[i])++cnt,dfs1(i);
	for(i=1;i<=n;i++)if(!vis[i])dfs(i);
	for(i=1,y=n-cnt;i<=cnt;i++)y+=flg[i];
	printf("%d\n",y);
	return 0;
}


#include<bits/stdc++.h>
const int N=1e5+10;
int n,m,col[N],dfn[N],cnt,cnt1,las;
bool flg[N];
std::vector<int>g[N],g1[N];
void dfs1(int u){col[u]=cnt;for(auto v:g1[u])if(!col[v])dfs1(v);}
void dfs(int u){if(dfn[u]){flg[col[u]]|=dfn[u]>las;return;}dfn[u]=++cnt1;for(auto v:g[u])dfs(v),las=cnt1;}
int main()
{
	int i,x,y;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++)scanf("%d%d",&x,&y),g[x].push_back(y),
	g1[x].push_back(y),g1[y].push_back(x);
	for(i=1;i<=n;i++)if(!col[i])++cnt,dfs1(i);
	for(i=1;i<=n;i++)if(!dfn[i])dfs(i),las=cnt1;
	for(i=1,y=n-cnt;i<=cnt;i++)y+=flg[i];
	printf("%d\n",y);
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
    int n, m;
    cin >> n >> m;
    vector<int> g[n], g2[n], deg(n, 0), cc(n, -1), stk;
    vector<bool> b;
    for (int i = 0; i < m; ++i) {
        int x, y;
        cin >> x >> y;
        --x, --y;
        g[x].push_back(y), g2[x].push_back(y), g2[y].push_back(x), ++deg[y];
    }
    for (int i = 0; i < n; ++i) if (cc[i] == -1) {
        stk.push_back(i), cc[i] = b.size(), b.push_back(false);
        while (stk.size()) {
            int x = stk.back();
            stk.pop_back();
            for (int y : g2[x]) if (cc[y] == -1) cc[y] = cc[i], stk.push_back(y);
        }
    }
    for (int i = 0; i < n; ++i) if (!deg[i]) stk.push_back(i);
    while (stk.size()) {
        int i = stk.back();
        stk.pop_back();
        for (int j : g[i]) if (--deg[j] == 0) stk.push_back(j);
    }
    for (int i = 0; i < n; ++i) if (deg[i]) b[cc[i]] = true;
    cout << n - b.size() + count(b.begin(), b.end(), true);
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<vector<int>> g, g2;
vector<int> low, stk;
vector<bool> vis;
int _t = 0, ans;
void dfs(int i) {
    int dep = low[i] = _t++;
    stk.push_back(i);
    for (int j : g[i]) {
        if (low[j] == -1) dfs(j);
        if (~vis[j]) low[i] = min(low[i], low[j]);
    }
    if (low[i] == dep) {
        ans += stk.back() != i;
        while (stk.back() != i) vis[stk.back()] = true, stk.pop_back();
        vis[i] = true, stk.pop_back();
    }
}
void dfs2(int i) {
    vis[i] = true;
    for (int j : g2[i]) if (!vis[j]) dfs2(j);
}
int main() {
    int n, m;
    cin >> n >> m;
    ans = n;
    g.resize(n), g2.resize(n), low.assign(n, -1), vis.assign(n, false);
    for (int i = 0; i < m; ++i) {
        int x, y;
        cin >> x >> y;
        --x, --y;
        g[x].push_back(y);
        g2[x].push_back(y), g2[y].push_back(x);
    }
    for (int i = 0; i < n; ++i) if (!vis[i]) dfs(i);
    vis.assign(n, false);
    for (int i = 0; i < n; ++i) if (!vis[i]) --ans, dfs2(i);
    cout << ans;
}


#include <bits/stdc++.h>

#define ff first
#define ss second
#define pb push_back
#define FOR(i,j,k) for(int i = j; i < (int)(k); i++)
#define FORV(i, v) FOR(i, 0, ((v).size()))
#define REP(i,j,k) for(int i = j; i >= (int)(k); i--)
#define setmax(i) const int maxn = (int) i;
#define setmod(i) const int MOD = (int) i;
#define all(a) a.begin(),a.end()
#define autodef(x,v) typeof(v) x = (v)
#define autoref(x,v) typeof(v)& x = (v)
#define forit(it, c) for (autodef(it, ((c).begin())); it != ((c).end()); ++it)

//typedef complex<double> Point;
//#define X real()
//#define Y imag()

using namespace std;

//ifstream fin("");
//ofstream fout("");
//#define cin fin
//#define cout fout

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef pair<pii,int> ppi;
typedef pair<pll,ll> ppl;
typedef pair<int,pii> pip;
typedef pair<ll,pll> plp;
typedef pair<pii,pii> ppp;

const int INF = (int) 2e9;
const ll INFL = (ll) 9e18;
const int MAXINT = ((~0) ^ (1 << 31));
const ll MAXLL = ((~0) ^ ((ll)1 << 63));

template<class T> inline T pow2(T a) { return a*a;}
template<class T> inline bool mineq(T& a, T b){return (a > b) ? (a=b, true) : false;}
template<class T> inline bool maxeq(T& a, T b){return (a < b) ? (a=b, true) : false;}

//srand (time(NULL));

const int maxn = 2e5;

ll n, m, mark[maxn], v, u, sum, vrt;

vector <ll> g[maxn], rg[maxn], vx, ans;

void dfs1(ll w){
    mark[w] = 1;
    for(int i = 0; i < g[w].size(); i ++){
        if(!mark[g[w][i]])
            dfs1(g[w][i]);
    }
    vx.pb(w);
}

void dfs2(ll w){
    mark[w] = 1;
    ans.pb(w);
    for(int i = 0; i < rg[w].size(); i ++){
        if(!mark[rg[w][i]])
            dfs2(rg[w][i]);
    }
}

int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for(int i = 0; i < m; i ++){
        cin >> v >> u;
        g[v].pb(u);
        rg[u].pb(v);
    }
    for(int i = 1; i <= n; i ++){
        if(!mark[i])
            dfs1(i);
    }
    memset(mark, 0, sizeof mark);
    reverse(vx.begin(), vx.end());
    for(int i = 0 ; i < n; i ++){
        if(!mark[vx[i]]){
            ans.clear();
            dfs2(vx[i]);
            if(ans.size() != 1)
                sum += ans.size();
            vrt ++;
        }
    }
    cout << sum + vrt - 1;
}


#include <bits/stdc++.h>

#define ff first
#define ss second
#define pb push_back
#define FOR(i,j,k) for(int i = j; i < (int)(k); i++)
#define FORV(i, v) FOR(i, 0, ((v).size()))
#define REP(i,j,k) for(int i = j; i >= (int)(k); i--)
#define setmax(i) const int maxn = (int) i;
#define setmod(i) const int MOD = (int) i;
#define all(a) a.begin(),a.end()
#define autodef(x,v) typeof(v) x = (v)
#define autoref(x,v) typeof(v)& x = (v)
#define forit(it, c) for (autodef(it, ((c).begin())); it != ((c).end()); ++it)

//typedef complex<double> Point;
//#define X real()
//#define Y imag()

using namespace std;

//ifstream fin("");
//ofstream fout("");
//#define cin fin
//#define cout fout

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef pair<pii,int> ppi;
typedef pair<pll,ll> ppl;
typedef pair<int,pii> pip;
typedef pair<ll,pll> plp;
typedef pair<pii,pii> ppp;

const int INF = (int) 2e9;
const ll INFL = (ll) 9e18;
const int MAXINT = ((~0) ^ (1 << 31));
const ll MAXLL = ((~0) ^ ((ll)1 << 63));

template<class T> inline T pow2(T a) { return a*a;}
template<class T> inline bool mineq(T& a, T b){return (a > b) ? (a=b, true) : false;}
template<class T> inline bool maxeq(T& a, T b){return (a < b) ? (a=b, true) : false;}

//srand (time(NULL));

const int maxn = 2e5;

ll n, m, mark[maxn], v, u, sum, vrt;

vector <ll> g[maxn], rg[maxn], vx, ans;

void dfs1(ll w){
    mark[w] = 1;
    for(int i = 0; i < g[w].size(); i ++){
        if(!mark[g[w][i]])
            dfs1(g[w][i]);
    }
    vx.pb(w);
}

void dfs2(ll w){
    mark[w] = 1;
    ans.pb(w);
    for(int i = 0; i < rg[w].size(); i ++){
        if(!mark[rg[w][i]])
            dfs2(rg[w][i]);
    }
}

int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for(int i = 0; i < m; i ++){
        cin >> v >> u;
        g[v].pb(u);
        rg[u].pb(v);
    }
    for(int i = 1; i <= n; i ++){
        if(!mark[i])
            dfs1(i);
    }
    memset(mark, 0, sizeof mark);
    reverse(vx.begin(), vx.end());
    for(int i = 0 ; i < vx.size(); i ++){
        if(!mark[vx[i]]){
            ans.clear();
            dfs2(vx[i]);
            if(ans.size() != 1)
                sum += ans.size();
            vrt ++;
        }
    }
    cout << sum + vrt - 1;
}


#include <bits/stdc++.h>

#define ff first
#define ss second
#define pb push_back
#define FOR(i,j,k) for(int i = j; i < (int)(k); i++)
#define FORV(i, v) FOR(i, 0, ((v).size()))
#define REP(i,j,k) for(int i = j; i >= (int)(k); i--)
#define setmax(i) const int maxn = (int) i;
#define setmod(i) const int MOD = (int) i;
#define all(a) a.begin(),a.end()
#define autodef(x,v) typeof(v) x = (v)
#define autoref(x,v) typeof(v)& x = (v)
#define forit(it, c) for (autodef(it, ((c).begin())); it != ((c).end()); ++it)

//typedef complex<double> Point;
//#define X real()
//#define Y imag()

using namespace std;

//ifstream fin("");
//ofstream fout("");
//#define cin fin
//#define cout fout

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef pair<pii,int> ppi;
typedef pair<pll,ll> ppl;
typedef pair<int,pii> pip;
typedef pair<ll,pll> plp;
typedef pair<pii,pii> ppp;

const int INF = (int) 2e9;
const ll INFL = (ll) 9e18;
const int MAXINT = ((~0) ^ (1 << 31));
const ll MAXLL = ((~0) ^ ((ll)1 << 63));

template<class T> inline T pow2(T a) { return a*a;}
template<class T> inline bool mineq(T& a, T b){return (a > b) ? (a=b, true) : false;}
template<class T> inline bool maxeq(T& a, T b){return (a < b) ? (a=b, true) : false;}

//srand (time(NULL));

const int maxn = 2e5;

ll n, m, v, u, mark[maxn], k, vt, sum, chk[maxn], cnt;

vector <ll> g[maxn], rg[maxn], vx, cg[maxn], ans;

ll dfs(ll w){
    mark[w] = 1;
    cnt ++;
    ll flg = chk[w];
    for(int i = 0; i < cg[w].size(); i ++){
        if(!mark[cg[w][i]])
            flg = max(dfs(cg[w][i]), flg);
    }
    return flg;
}

void dfs1(ll w){
    mark[w] = 1;
    for(int i = 0; i < g[w].size(); i ++){
        if(!mark[g[w][i]])
            dfs1(g[w][i]);
    }
    vx.pb(w);
}

void dfs2(ll w){
    mark[w] = 1;
    ans.pb(w);
    for(int i = 0; i < rg[w].size(); i ++){
        if(!mark[rg[w][i]])
            dfs2(rg[w][i]);
    }
}

int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for(int i = 0; i < m; i ++){
        cin >> v >> u;
        g[v].pb(u);
        rg[u].pb(v);
        cg[v].pb(u);
        cg[u].pb(v);
    }
    for(int i = 1; i <= n; i ++){
        if(!mark[i])
            dfs1(i);
    }
    reverse(vx.begin(), vx.end());
    memset(mark, 0 ,sizeof mark);
    for(int i = 0; i < vx.size(); i ++){
        if(!mark[vx[i]]){
            ans.clear();
            dfs2(vx[i]);
            if(ans.size() != 1){
                for(int j = 0; j < ans.size(); j ++)
                    chk[ans[j]] = 1;
            }
        }
    }
    memset(mark, 0, sizeof mark);
    for(int i = 1; i <= n; i ++){
        if(!mark[i]){
            cnt = 0;
            if(dfs(i))
                sum += cnt;
            else
                sum += cnt - 1;
        }
    }
    cout << sum;
}


#include <bits/stdc++.h>

#define ff first
#define ss second
#define pb push_back
#define FOR(i,j,k) for(int i = j; i < (int)(k); i++)
#define FORV(i, v) FOR(i, 0, ((v).size()))
#define REP(i,j,k) for(int i = j; i >= (int)(k); i--)
#define setmax(i) const int maxn = (int) i;
#define setmod(i) const int MOD = (int) i;
#define all(a) a.begin(),a.end()
#define autodef(x,v) typeof(v) x = (v)
#define autoref(x,v) typeof(v)& x = (v)
#define forit(it, c) for (autodef(it, ((c).begin())); it != ((c).end()); ++it)

//typedef complex<double> Point;
//#define X real()
//#define Y imag()

using namespace std;

//ifstream fin("");
//ofstream fout("");
//#define cin fin
//#define cout fout

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef pair<pii,int> ppi;
typedef pair<pll,ll> ppl;
typedef pair<int,pii> pip;
typedef pair<ll,pll> plp;
typedef pair<pii,pii> ppp;

const int INF = (int) 2e9;
const ll INFL = (ll) 9e18;
const int MAXINT = ((~0) ^ (1 << 31));
const ll MAXLL = ((~0) ^ ((ll)1 << 63));

template<class T> inline T pow2(T a) { return a*a;}
template<class T> inline bool mineq(T& a, T b){return (a > b) ? (a=b, true) : false;}
template<class T> inline bool maxeq(T& a, T b){return (a < b) ? (a=b, true) : false;}

//srand (time(NULL));

const int maxn = 2e5;

ll n, m, mark[maxn], v, u, sum, vrt, chk[maxn], k;

vector <ll> g[maxn], rg[maxn], vx, ans, cg[maxn];

void dfs(ll w){
    mark[w] = 1;
    for(int i = 0; i < cg[w].size(); i ++){
        if(!mark[cg[w][i]])
            dfs(cg[w][i]);
    }
}

void dfs1(ll w){
    mark[w] = 1;
    for(int i = 0; i < g[w].size(); i ++){
        if(!mark[g[w][i]])
            dfs1(g[w][i]);
    }
    vx.pb(w);
}

void dfs2(ll w){
    mark[w] = 1;
    ans.pb(w);
    for(int i = 0; i < rg[w].size(); i ++){
        if(!mark[rg[w][i]])
            dfs2(rg[w][i]);
    }
}

int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for(int i = 0; i < m; i ++){
        cin >> v >> u;
        g[v].pb(u);
        rg[u].pb(v);
        chk[v] = 1;
        chk[u] = 1;
        cg[v].pb(u);
        cg[u].pb(v);
    }
    for(int i = 1; i <= n; i ++){
        if(!mark[i]){
            dfs(i);
            k ++;
        }
    }
    k --;
    memset(mark, 0, sizeof mark);
    for(int i = 1; i <= n; i ++){
        if(!mark[i])
            dfs1(i);
    }
    memset(mark, 0, sizeof mark);
    reverse(vx.begin(), vx.end());
    for(int i = 0 ; i < vx.size(); i ++){
        if(!mark[vx[i]]){
            ans.clear();
            dfs2(vx[i]);
            if(ans.size() != 1)
                sum += ans.size();
            vrt ++;
        }
    }
    cout << sum + vrt - 1 - k;
}


#include <bits/stdc++.h>

#define ff first
#define ss second
#define pb push_back
#define FOR(i,j,k) for(int i = j; i < (int)(k); i++)
#define FORV(i, v) FOR(i, 0, ((v).size()))
#define REP(i,j,k) for(int i = j; i >= (int)(k); i--)
#define setmax(i) const int maxn = (int) i;
#define setmod(i) const int MOD = (int) i;
#define all(a) a.begin(),a.end()
#define autodef(x,v) typeof(v) x = (v)
#define autoref(x,v) typeof(v)& x = (v)
#define forit(it, c) for (autodef(it, ((c).begin())); it != ((c).end()); ++it)

//typedef complex<double> Point;
//#define X real()
//#define Y imag()

using namespace std;

//ifstream fin("");
//ofstream fout("");
//#define cin fin
//#define cout fout

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef pair<pii,int> ppi;
typedef pair<pll,ll> ppl;
typedef pair<int,pii> pip;
typedef pair<ll,pll> plp;
typedef pair<pii,pii> ppp;

const int INF = (int) 2e9;
const ll INFL = (ll) 9e18;
const int MAXINT = ((~0) ^ (1 << 31));
const ll MAXLL = ((~0) ^ ((ll)1 << 63));

template<class T> inline T pow2(T a) { return a*a;}
template<class T> inline bool mineq(T& a, T b){return (a > b) ? (a=b, true) : false;}
template<class T> inline bool maxeq(T& a, T b){return (a < b) ? (a=b, true) : false;}

//srand (time(NULL));

const int maxn = 2e5;

ll n, m, v, u, mark[maxn], k, vt, sum, cnt;

vector <ll> g[maxn], rg[maxn], vx, cg[maxn];

void dfs(ll w){
    mark[w] = 1;
    for(int i = 0; i < cg[w].size(); i ++){
        if(!mark[cg[w][i]])
            dfs(cg[w][i]);
    }
}

void dfs1(ll w){
    mark[w] = 1;
    for(int i = 0; i < g[w].size(); i ++){
        if(!mark[g[w][i]])
            dfs1(g[w][i]);
    }
    vx.pb(w);
}

void dfs2(ll w){
    mark[w] = 1;
    cnt ++;
    for(int i = 0; i < rg[w].size(); i ++){
        if(!mark[rg[w][i]])
            dfs2(rg[w][i]);
    }
}

int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for(int i = 0; i < m; i ++){
        cin >> v >> u;
        g[v].pb(u);
        rg[u].pb(v);
        cg[v].pb(u);
        cg[u].pb(v);
    }
    for(int i = 1; i <= n; i ++){
        if(!mark[i]){
            dfs(i);
            k ++;
        }
    }
    memset(mark, 0, sizeof mark);
    for(int i = 1; i <= n; i ++){
        if(!mark[i])
            dfs1(i);
    }
    reverse(vx.begin(), vx.end());
    memset(mark, 0 ,sizeof mark);
    for(int i = 0; i < vx.size(); i ++){
        if(!mark[vx[i]]){
            cnt = 0;
            dfs2(vx[i]);
            if(cnt != 1)
                sum += cnt;
            vt ++;
        }
    }
    cout << sum + (vt - 1) - (k - 1);
}


#include <cstdio>
#include <cstdlib>
#include <vector>

std::vector<int> conns[100007];
std::vector<int> rconns[100007];
char vis[100007];
char gvis[100007];
int po[100007];
int poi = 1;
int gid[100007];
int gcnt[100007];
int gidi = 1;

void do_postorder(int i) {
    if (vis[i] == 1)
        return;
    vis[i] = 1;
    for (int j : conns[i])
        do_postorder(j);
    po[poi++] = i;
}
void do_2(int i, int g) {
    if (vis[i] == 2)
        return;
    vis[i] = 2;
    gid[i] = g;
    gcnt[g]++;
    for (int j : rconns[i])
        do_2(j, g);
}
void flood(int i, int& rcnt, int& radd, int from) {
    if (vis[i] == 3)
        return;
    vis[i] = 3;
    if (!gvis[gid[i]]) {
        rcnt++;
        gvis[gid[i]] = true;
        if (gcnt[gid[i]] > 1)
            radd += gcnt[gid[i]];
        if (gcnt[gid[from]] > 1)
            radd--;
    }
    for (int j : conns[i])
        flood(j, rcnt, radd, i);
    for (int j : rconns[i])
        flood(j, rcnt, radd, i);
}

int main() {
    int n, m, a, b;
    scanf("%i %i", &n, &m);
    for (int i = 0; i < m; i++) {
        scanf("%i %i", &a, &b);
        conns[a].push_back(b);
        rconns[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
        do_postorder(i);
    for (int i = n; i >= 1; i--) {
        if (vis[po[i]] != 2)
            do_2(po[i], gidi++);
    }
    int res = 0;
    for (int i = 1; i <= n; i++) {
        if (vis[i] == 3)
            continue;
        int rcnt = 0, radd = 0;
        flood(i, rcnt, radd, -1);
        res += rcnt - 1;
        res += radd;
    }
    printf("%i\n", res);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <vector>

std::vector<int> conns[100007];
std::vector<int> rconns[100007];
char vis[100007];
char gvis[100007];
int po[100007];
int poi = 1;
int gid[100007];
int gcnt[100007];
int gidi = 1;

void do_postorder(int i) {
    if (vis[i] == 1)
        return;
    vis[i] = 1;
    for (int j : conns[i])
        do_postorder(j);
    po[poi++] = i;
}
void do_2(int i, int g) {
    if (vis[i] == 2)
        return;
    vis[i] = 2;
    gid[i] = g;
    gcnt[g]++;
    for (int j : rconns[i])
        do_2(j, g);
}
void flood(int i, int& rcnt, int& radd, int from) {
    if (vis[i] == 3)
        return;
    vis[i] = 3;
    if (!gvis[gid[i]]) {
        rcnt++;
        gvis[gid[i]] = true;
        if (gcnt[gid[i]] > 1) {
            radd += gcnt[gid[i]];
            if (gcnt[gid[from]] > 1)
                radd--;
        }
    }
    for (int j : conns[i])
        flood(j, rcnt, radd, i);
    for (int j : rconns[i])
        flood(j, rcnt, radd, i);
}

int main() {
    int n, m, a, b;
    scanf("%i %i", &n, &m);
    for (int i = 0; i < m; i++) {
        scanf("%i %i", &a, &b);
        conns[a].push_back(b);
        rconns[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
        do_postorder(i);
    for (int i = n; i >= 1; i--) {
        if (vis[po[i]] != 2)
            do_2(po[i], gidi++);
    }
    int res = 0;
    for (int i = 1; i <= n; i++) {
        if (vis[i] == 3)
            continue;
        int rcnt = 0, radd = 0;
        flood(i, rcnt, radd, 0);
        res += rcnt - 1;
        res += radd;
    }
    printf("%i\n", res);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <vector>

std::vector<int> conns[100007];
std::vector<int> rconns[100007];
char vis[100007];
char gvis[100007];
int po[100007];
int poi = 1;
int gid[100007];
int gcnt[100007];
int gidi = 1;

void do_postorder(int i) {
    if (vis[i] == 1)
        return;
    vis[i] = 1;
    for (int j : conns[i])
        do_postorder(j);
    po[poi++] = i;
}
void do_2(int i, int g) {
    if (vis[i] == 2)
        return;
    vis[i] = 2;
    gid[i] = g;
    gcnt[g]++;
    for (int j : rconns[i])
        do_2(j, g);
}
void flood(int i, int& rcnt, int& radd) {
    if (vis[i] == 3)
        return;
    vis[i] = 3;
    if (!gvis[gid[i]]) {
        rcnt++;
        gvis[gid[i]] = true;
        if (gcnt[gid[i]] > 1)
            radd += gcnt[gid[i]];
    }
    for (int j : conns[i])
        flood(j, rcnt, radd);
    for (int j : rconns[i])
        flood(j, rcnt, radd);
}

int main() {
    int n, m, a, b;
    scanf("%i %i", &n, &m);
    for (int i = 0; i < m; i++) {
        scanf("%i %i", &a, &b);
        conns[a].push_back(b);
        rconns[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
        do_postorder(i);
    for (int i = n; i >= 1; i--) {
        if (vis[po[i]] != 2)
            do_2(po[i], gidi++);
    }
    int res = 0;
    for (int i = 1; i <= n; i++) {
        if (vis[i] == 3)
            continue;
        int rcnt = 0, radd = 0;
        flood(i, rcnt, radd);
        res += rcnt - 1;
        res += radd;
    }
    printf("%i\n", res);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <vector>

std::vector<int> conns[100007];
std::vector<int> rconns[100007];
char vis[100007];
char gvis[100007];
int po[100007];
int poi = 1;
int gid[100007];
int gcnt[100007];
int gidi = 1;

void do_postorder(int i) {
    if (vis[i] == 1)
        return;
    vis[i] = 1;
    for (int j : conns[i])
        do_postorder(j);
    po[poi++] = i;
}
void do_2(int i, int g) {
    if (vis[i] == 2)
        return;
    vis[i] = 2;
    gid[i] = g;
    gcnt[g]++;
    for (int j : rconns[i])
        do_2(j, g);
}
void flood(int i, int& rcnt, int& radd) {
    if (vis[i] == 3)
        return;
    vis[i] = 3;
    if (!gvis[gid[i]]) {
        rcnt++;
        gvis[gid[i]] = true;
        if (gcnt[gid[i]] > 1) {
            radd += gcnt[gid[i]];

            for (int j : conns[i])
                if (gid[j] != gid[i] && gvis[gid[j]] && gcnt[gid[j]] > 1)
                    radd--;
            for (int j : rconns[i])
                if (gid[j] != gid[i] && gvis[gid[j]] && gcnt[gid[j]] > 1)
                    radd--;
        }
    }
    for (int j : conns[i])
        flood(j, rcnt, radd);
    for (int j : rconns[i])
        flood(j, rcnt, radd);
}

int main() {
    int n, m, a, b;
    scanf("%i %i", &n, &m);
    for (int i = 0; i < m; i++) {
        scanf("%i %i", &a, &b);
        conns[a].push_back(b);
        rconns[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
        do_postorder(i);
    for (int i = n; i >= 1; i--) {
        if (vis[po[i]] != 2)
            do_2(po[i], gidi++);
    }
    int res = 0;
    for (int i = 1; i <= n; i++) {
        if (vis[i] == 3)
            continue;
        int rcnt = 0, radd = 0;
        flood(i, rcnt, radd);
        res += rcnt - 1;
        res += radd;
    }
    printf("%i\n", res);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <vector>

std::vector<int> conns[100007];
std::vector<int> rconns[100007];
char vis[100007];
char gvis[100007];
int po[100007];
int poi = 1;
int gid[100007];
int gcnt[100007];
int gidi = 1;

void do_postorder(int i) {
    if (vis[i] == 1)
        return;
    vis[i] = 1;
    for (int j : conns[i])
        do_postorder(j);
    po[poi++] = i;
}
void do_2(int i, int g) {
    if (vis[i] == 2)
        return;
    vis[i] = 2;
    gid[i] = g;
    gcnt[g]++;
    for (int j : rconns[i])
        do_2(j, g);
}
void flood(int i, int& rcnt, bool& rcycle) {
    if (vis[i] == 3)
        return;
    vis[i] = 3;
    rcnt++;
    if (!gvis[gid[i]]) {
        gvis[gid[i]] = true;
        if (gcnt[gid[i]] > 1)
            rcycle = true;
    }
    for (int j : conns[i])
        flood(j, rcnt, rcycle);
    for (int j : rconns[i])
        flood(j, rcnt, rcycle);
}

int main() {
    int n, m, a, b;
    scanf("%i %i", &n, &m);
    for (int i = 0; i < m; i++) {
        scanf("%i %i", &a, &b);
        conns[a].push_back(b);
        rconns[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
        do_postorder(i);
    for (int i = n; i >= 1; i--) {
        if (vis[po[i]] != 2)
            do_2(po[i], gidi++);
    }
    int res = 0;
    for (int i = 1; i <= n; i++) {
        int rcnt = 0;
        bool rcycle = false;
        flood(i, rcnt, rcycle);
        if (rcnt == 0)
            continue;
        res += rcnt - (rcycle ? 0 : 1);
    }
    printf("%i\n", res);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <vector>

std::vector<int> conns[100007];
std::vector<int> rconns[100007];
char vis[100007];
char gvis[100007];
int po[100007];
int poi = 1;
int gid[100007];
int gcnt[100007];
int gidi = 1;

void do_postorder(int i) {
    if (vis[i] == 1)
        return;
    vis[i] = 1;
    for (int j : conns[i])
        do_postorder(j);
    po[poi++] = i;
}
void do_2(int i, int g) {
    if (vis[i] == 2)
        return;
    vis[i] = 2;
    gid[i] = g;
    gcnt[g]++;
    for (int j : rconns[i])
        do_2(j, g);
}
void flood(int i, int& rcnt, int& radd, int from) {
    if (vis[i] == 3)
        return;
    vis[i] = 3;
    if (!gvis[gid[i]]) {
        rcnt++;
        gvis[gid[i]] = true;
        if (gcnt[gid[i]] > 1) {
            radd += gcnt[gid[i]];
            if (gcnt[gid[from]] > 1)
                radd--;
        }
    }
    for (int j : conns[i])
        flood(j, rcnt, radd, i);
    for (int j : rconns[i])
        flood(j, rcnt, radd, i);
}

int main() {
    int n, m, a, b;
    scanf("%i %i", &n, &m);
    for (int i = 0; i < m; i++) {
        scanf("%i %i", &a, &b);
        conns[a].push_back(b);
        rconns[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
        do_postorder(i);
    for (int i = n; i >= 1; i--) {
        if (vis[po[i]] != 2)
            do_2(po[i], gidi++);
    }
    int res = 0;
    for (int i = 1; i <= n; i++) {
        if (vis[i] == 3)
            continue;
        int rcnt = 0, radd = 0;
        flood(i, rcnt, radd, -1);
        res += rcnt - 1;
        res += radd;
    }
    printf("%i\n", res);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define fore(i, s, e) for(int i = s; i < e; i++)
#define FIN ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define pb push_back
#define fst first
#define snd second
typedef long long ll;

const int MAXN = 1e5;

// MAXN: max number of nodes or 2 * max number of variables (2SAT)
bool truth[MAXN]; // truth[cmp[i]]=value of variable i (2SAT)
int nvar;int neg(int x){return MAXN-1-x;} // (2SAT)
vector<int> g[MAXN];
int n, m,lw[MAXN],idx[MAXN],qidx,cmp[MAXN],qcmp;
stack<int> st;
void tjn(int u){
	lw[u]=idx[u]=++qidx;
	st.push(u);cmp[u]=-2;
	for(int v:g[u]){
		if(!idx[v]||cmp[v]==-2){
			if(!idx[v]) tjn(v);
			lw[u]=min(lw[u],lw[v]);
		}
	}
	if(lw[u]==idx[u]){
		int x,l=-1;
		do{x=st.top();st.pop();cmp[x]=qcmp;if(min(x,neg(x))<nvar)l=x;}
		while(x!=u);
		if(l!=-1)truth[qcmp]=(cmp[neg(l)]<0); // (2SAT)
		qcmp++;
	}
}
void scc(){
	memset(idx,0,sizeof(idx));qidx=0;
	memset(cmp,-1,sizeof(cmp));qcmp=0;
	fore(i,0,n)if(!idx[i])tjn(i);
}
vector<int> gn[MAXN];

bool vis[MAXN];

int dfs(int x) {
	vis[x] = true;
	int r = 1;
	for(auto v : gn[x]) if(!vis[v]) r += dfs(v);
	return r;
}

int main() {
    cin >> n >> m;
    fore(i, 0, m) {
        int a, b; cin >> a >> b; a--, b--;
        g[a].pb(b);
    }
    scc();
    map<int, int> q;
    fore(i, 0, n) {
        q[cmp[i]]++;
    }
    ll res = 0;
    for(auto x : q) if(x.snd > 1) {
        res += x.snd;
    }
    q.clear();

    fore(i, 0, n) {
        for(auto x : g[i]) gn[cmp[i]].pb(cmp[x]), gn[cmp[x]].pb(cmp[i]);
    }

	fore(i, 0, qcmp) if(!vis[i]) res += dfs(i) - 1;
    cout << res << endl;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define fore(i, s, e) for(int i = s; i < e; i++)
#define FIN ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define pb push_back
#define fst first
#define snd second
typedef long long ll;

const int MAXN = 2e5;

// MAXN: max number of nodes or 2 * max number of variables (2SAT)
bool truth[MAXN]; // truth[cmp[i]]=value of variable i (2SAT)
int nvar;int neg(int x){return MAXN-1-x;} // (2SAT)
vector<int> g[MAXN];
int n, m,lw[MAXN],idx[MAXN],qidx,cmp[MAXN],qcmp;
stack<int> st;
void tjn(int u){
	lw[u]=idx[u]=++qidx;
	st.push(u);cmp[u]=-2;
	for(int v:g[u]){
		if(!idx[v]||cmp[v]==-2){
			if(!idx[v]) tjn(v);
			lw[u]=min(lw[u],lw[v]);
		}
	}
	if(lw[u]==idx[u]){
		int x,l=-1;
		do{x=st.top();st.pop();cmp[x]=qcmp;if(min(x,neg(x))<nvar)l=x;}
		while(x!=u);
		if(l!=-1)truth[qcmp]=(cmp[neg(l)]<0); // (2SAT)
		qcmp++;
	}
}
void scc(){
	memset(idx,0,sizeof(idx));qidx=0;
	memset(cmp,-1,sizeof(cmp));qcmp=0;
	fore(i,0,n)if(!idx[i])tjn(i);
}
set<int> gn[MAXN];

bool vis[MAXN];

bool f = true;

map<int, int> q;

void dfs(int x) {
	vis[x] = true;
	f = f && q[x] == 1;
	for(auto v : gn[x]) if(!vis[v]) dfs(v);
}

int main() {
    cin >> n >> m;
    fore(i, 0, m) {
        int a, b; cin >> a >> b; a--, b--;
        g[a].pb(b);
    }
    scc();
    fore(i, 0, n) {
        q[cmp[i]]++;
    }
    ll res = n;

    fore(i, 0, n) {
        for(auto x : g[i]) if(cmp[x] != cmp[i]) gn[cmp[i]].insert(cmp[x]), gn[cmp[x]].insert(cmp[i]);
    }

	fore(i, 0, qcmp) if(!vis[i]) dfs(i), res -= f, f = true;
    cout << res << endl;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define fore(i, s, e) for(int i = s; i < e; i++)
#define FIN ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define pb push_back
#define fst first
#define snd second
typedef long long ll;

const int MAXN = 1e5;

// MAXN: max number of nodes or 2 * max number of variables (2SAT)
bool truth[MAXN]; // truth[cmp[i]]=value of variable i (2SAT)
int nvar;int neg(int x){return MAXN-1-x;} // (2SAT)
vector<int> g[MAXN];
int n, m,lw[MAXN],idx[MAXN],qidx,cmp[MAXN],qcmp;
stack<int> st;
void tjn(int u){
	lw[u]=idx[u]=++qidx;
	st.push(u);cmp[u]=-2;
	for(int v:g[u]){
		if(!idx[v]||cmp[v]==-2){
			if(!idx[v]) tjn(v);
			lw[u]=min(lw[u],lw[v]);
		}
	}
	if(lw[u]==idx[u]){
		int x,l=-1;
		do{x=st.top();st.pop();cmp[x]=qcmp;if(min(x,neg(x))<nvar)l=x;}
		while(x!=u);
		if(l!=-1)truth[qcmp]=(cmp[neg(l)]<0); // (2SAT)
		qcmp++;
	}
}
void scc(){
	memset(idx,0,sizeof(idx));qidx=0;
	memset(cmp,-1,sizeof(cmp));qcmp=0;
	fore(i,0,n)if(!idx[i])tjn(i);
}
set<int> gn[MAXN];

bool vis[MAXN];

int dfs(int x) {
	vis[x] = true;
	int r = 1;
	for(auto v : gn[x]) if(!vis[v]) r += dfs(v);
	return r;
}

int main() {
    cin >> n >> m;
    fore(i, 0, m) {
        int a, b; cin >> a >> b; a--, b--;
        g[a].pb(b);
    }
    scc();
    map<int, int> q;
    fore(i, 0, n) {
        q[cmp[i]]++;
    }
    ll res = 0;
    for(auto x : q) if(x.snd > 1) {
        res += x.snd;
    }
    q.clear();

    fore(i, 0, n) {
        for(auto x : g[i]) if(cmp[x] != cmp[i]) gn[cmp[i]].insert(cmp[x]), gn[cmp[x]].insert(cmp[i]);
    }

	fore(i, 0, n) if(!vis[cmp[i]]) res += dfs(cmp[i]) - 1;
    cout << res << endl;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define fore(i, s, e) for(int i = s; i < e; i++)
#define FIN ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define pb push_back
#define fst first
#define snd second
typedef long long ll;

const int MAXN = 1e5;

// MAXN: max number of nodes or 2 * max number of variables (2SAT)
bool truth[MAXN]; // truth[cmp[i]]=value of variable i (2SAT)
int nvar;int neg(int x){return MAXN-1-x;} // (2SAT)
vector<int> g[MAXN];
int n, m,lw[MAXN],idx[MAXN],qidx,cmp[MAXN],qcmp;
stack<int> st;
void tjn(int u){
	lw[u]=idx[u]=++qidx;
	st.push(u);cmp[u]=-2;
	for(int v:g[u]){
		if(!idx[v]||cmp[v]==-2){
			if(!idx[v]) tjn(v);
			lw[u]=min(lw[u],lw[v]);
		}
	}
	if(lw[u]==idx[u]){
		int x,l=-1;
		do{x=st.top();st.pop();cmp[x]=qcmp;if(min(x,neg(x))<nvar)l=x;}
		while(x!=u);
		if(l!=-1)truth[qcmp]=(cmp[neg(l)]<0); // (2SAT)
		qcmp++;
	}
}
void scc(){
	memset(idx,0,sizeof(idx));qidx=0;
	memset(cmp,-1,sizeof(cmp));qcmp=0;
	fore(i,0,n)if(!idx[i])tjn(i);
}
vector<int> gn[MAXN];

bool vis[MAXN];

int dfs(int x) {
	vis[x] = true;
	int r = 1;
	for(auto v : gn[x]) if(!vis[v]) r += dfs(v);
	return r;
}

int main() {
    cin >> n >> m;
    fore(i, 0, m) {
        int a, b; cin >> a >> b; a--, b--;
        g[a].pb(b);
    }
    scc();
    map<int, int> q;
    fore(i, 0, n) {
        q[cmp[i]]++;
    }
    ll res = 0;
    for(auto x : q) if(x.snd > 1) {
        res += x.snd;
    }
    q.clear();

    fore(i, 0, n) {
        for(auto x : g[i]) gn[cmp[i]].pb(cmp[x]), gn[cmp[x]].pb(cmp[i]);
    }

	fore(i, 0, n) if(!vis[cmp[i]]) res += dfs(cmp[i]) - 1;
    cout << res << endl;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define pii pair <int , int>
#define F first
#define S second

const int N = 1e5 + 10;
int mark[N], comp[N], C[N], V;
vector <int> ig[N], og[N], g[N], vi;
vector <pii> edge;

void odfs(int v)
{
    mark[v] = 1;
    for (int u : og[v]) if (!mark[u]) odfs(u);
    vi.push_back(v);
}

void idfs(int v, int c)
{
    comp[v] = c;
    C[c] ++;
    for (int u : ig[v]) if (!comp[u]) idfs(u, c);
}

bool dfs(int v)
{
    V += C[v];
    mark[v] = 1;
    bool b = 0;
    if (C[v] > 1) b = 1;
    for (int u : g[v]) if (!mark[u]) b |= dfs(u);
    return b;
}

int main()
{
    IOS ;
    int n, m; cin >> n >> m;
    for (int i = 0; i < m; i ++) {
        int u, v; cin >> u >> v;
        og[u].push_back(v);
        ig[v].push_back(u);
        edge.push_back({u, v});
    }
    for (int i = 1; i <= n; i ++) if (!mark[i]) odfs(i);
    reverse(vi.begin(), vi.end());
    int c = 1;
    for (int i : vi) if (!comp[i]) idfs(i, c ++);
    for (auto p : edge) {
        int u = comp[p.F], v = comp[p.S];
        if (u != v) {
            g[u].push_back(v);
            g[v].push_back(u);
        }
    }
    int ans = 0;
    memset(mark, 0, sizeof mark);
    for (int i = 1; i < c; i ++) if (!mark[i]) {
        V = 0;
        bool b = dfs(i);
        if (b) ans += V;
        else ans += V - 1;
    }
    cout << ans << "\n";
}


#include <bits/stdc++.h>

using namespace std;
#define ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define pii pair <int , int>
#define F first
#define S second

const int N = 1e5 + 10;
int mark[N], comp[N], C[N], V;
vector <int> ig[N], og[N], g[N], vi;
vector <pii> edge;

void odfs(int v)
{
    mark[v] = 1;
    for (int u : og[v]) if (!mark[u]) odfs(u);
    vi.push_back(v);
}

void idfs(int v, int c)
{
    comp[v] = c;
    C[c] ++;
    for (int u : ig[v]) if (!comp[u]) idfs(u, c);
}

bool dfs(int v)
{
    V += C[v];
    mark[v] = 1;
    bool b = 0;
    if (C[v] > 1) b = 1;
    for (int u : g[v]) if (!mark[u]) b |= dfs(u);
    return b;
}

int main()
{
    IOS ;
    int n, m; cin >> n >> m;
    for (int i = 0; i < m; i ++) {
        int u, v; cin >> u >> v;
        og[u].push_back(v);
        ig[v].push_back(u);
        edge.push_back({u, v});
    }
    for (int i = 1; i <= n; i ++) if (!mark[i]) odfs(i);
    reverse(vi.begin(), vi.end());
    int c = 1;
    for (int i : vi) if (!comp[i]) idfs(i, c ++);
    for (auto p : edge) {
        int u = comp[p.F], v = comp[p.S];
        if (u != v) {
            g[u].push_back(v);
            g[v].push_back(u);
        }
    }
    int ans = 0;
    memset(mark, 0, sizeof mark);
    for (int i = 1; i < c; i ++) if (!mark[i]) {
        V = 0;
        bool b = dfs(i);
        if (b) ans += V;
        else ans += V - 1;
    }
    cout << ans << "\n";
}