#include <iostream>
//#include <bits/stdc++.h>
#include <stack>
#include <vector>
#include <cstring>
using namespace std;
vector<int>graph[5005];
vector<int>rev_graph[5005];
bool visited[5005];

stack<int>s;

int najgolem=-2e9;
int najmal=2e9;
int brojac1=0;

void dfs(int node){
visited[node]=true;
for(int i=0; i<graph[node].size(); i++){
    int sosed=graph[node][i];
    if(!visited[sosed]){
        dfs(sosed);
    }
}
s.push(node);
}
void rev_dfs(int node){
visited[node]=true;
brojac1+=1;
for(int i=0; i<rev_graph[node].size(); i++){
    int rev_sosed=rev_graph[node][i];
    if(!visited[rev_sosed]){
        rev_dfs(rev_sosed);
    }
}
}
int main()
{
    int brojac=0;

    int p, t;
    cin>>p>>t;
    memset(visited, false, sizeof visited);
    for(int i=0; i<t; i++){
        int a, b;
        cin>>a>>b;
        graph[a].push_back(b);
        rev_graph[b].push_back(a);
    }
    for(int i=1; i<=p; i++){
        if(!visited[i]){
            dfs(i);
        }
    }
    memset(visited, false, sizeof visited);

    while(!s.empty()){
        int node=s.top();
        if(!visited[node]){
            rev_dfs(node);
//            cout << brojac1 << endl;
            if(najgolem<brojac1){
                najgolem=brojac1;
            }
            if(najmal>brojac1){
                najmal=brojac1;
            }
            brojac1=0;
            brojac+=1;
        }
        s.pop();
    }

    cout<<brojac<<endl;
    cout<<najmal<<" "<<najgolem;
    return 0;
}
