#pragma GCC optimize("Ofast,inline")

#include <bits/stdc++.h>

using namespace std;

//#define int int64_t
#define fi first
#define se second
mt19937 gen(time(0));

const int N = 2e3 + 12;
vector <int> g[N];
vector <int> G[N];

int used[N];
vector <int> order;
void go1(int v) {
    used[v] = 1;
    for(auto to : g[v]) {
        if(!used[to])
            go1(to);
    }
    order.push_back(v);
    return;
}

int sz[N];
int C = 0;
void go2(int v) {
    used[v] = C;
    sz[C]++;
    for(auto to : G[v]) {
        if(!used[to])
            go2(to);
    }
    return;
}

vector <int> sg[N];
int cnt = 0;
void dfs(int v) {
    cnt++;
    used[v] = 1;
    for(auto to : sg[v]) {
        if(!used[to])
            dfs(to);
    }
    return;
}

int32_t main() {
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif // LOCAL
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int n, m, G2;
    cin >> n >> m >> G2;
    for(int i = 0; i < m; ++i) {
        int v, u;
        cin >> v >> u;
        G[u].push_back(v);
        g[v].push_back(u);
    }
    for(int i = 1; i <= n; ++i) {
        if(!used[i])
            go1(i);
    }
    reverse(order.begin(), order.end());
    fill(used, used + N, 0);
    for(auto v : order) {
        if(!used[v]) {
            ++C;
            go2(v);
        }
    }
    int ans = 0;
    for(int i = 1; i <= C; ++i) {
        ans += sz[i] - 1;
    }
    for(int v = 1; v <= n; ++v) {
        for(auto to : g[v]) {
            if(used[v] != used[to]) {
                sg[used[v]].push_back(used[to]);
                sg[used[to]].push_back(used[v]);
                ans++;
            }
        }
    }
    fill(used, used + N, 0);
    for(int i = 1; i <= C; ++i) {
        if(used[i])
            continue;
        dfs(i);
        ans -= (cnt - 1);
        cnt = 0;
    }
    cout << ans << ' ' << 3;
    return 0;
}
