#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long
#define db long double

using namespace std;
//using namespace __gnu_pbds;
//using ordered_set = tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>;

vector<int> tin, used, color;
vector<vector<int>> g;

void dfs1(int idx) {
    used[idx] = true;

    for (int to : g[idx]) {
        if (!used[to]) {
            dfs1(to);
        }
    }

    tin.push_back(idx);
}

void dfs2(int idx, int col) {
    color[idx] = col;

    for (int to : g[idx]) {
        if (!color[to]) {
            dfs2(to, col);
        }
    }
}

vector<int> kss(vector<pair<int, int>> &edges, int n) {
    g.assign(n + 1, {});

    for (auto [u, v] : edges) {
        g[u].push_back(v);
    }

    used.assign(n + 1, 0);

    int t = 0;
    for (int i = 1; i <= n; ++i) {
        if (!used[i]) {
            dfs1(i);
        }
    }

    g.assign(n + 1, {});
    for (auto [u, v] : edges) {
        g[v].push_back(u);
    }

    color.assign(n + 1, 0);

    reverse(tin.begin(), tin.end());
    for (int i : tin) {
        if (!color[i]) {
            dfs2(i, ++t);
        }
    }

    vector<int> val(t + 1, 0);

    t = 1;
    for (int i = 1; i <= n; ++i) {
        if (!val[color[i]]) {
            val[color[i]] = ++t;
        }
        color[i] = val[color[i]];
    }

    return color;
}

void solve() {
    int n, m, tp; cin >> n >> m >> tp;

    vector<pair<int, int>> edges;
    for (int i = 0; i < m; ++i) {
        int u, v; cin >> u >> v;
        edges.emplace_back(u, v);
    }

    vector<int> owr = kss(edges, n);

    map<int, int> mp;

    vector<bool> can(1 << m, true);

    for (int mask = 1; mask < (1 << m); ++mask) {
        if (can[mask]) {
            vector<pair<int, int>> edge;
            for (int i = 0; i < m; ++i) {
                if ((mask >> i) % 2) {
                    edge.emplace_back(edges[i].second, edges[i].first);
                } else {
                    edge.push_back(edges[i]);
                }
            }

            if (kss(edge, n) == owr) {
                can[mask] = false;
            }
        }

        if (can[mask]) {
            int cnt = 0;

            for (int i = 0; i < m; ++i) {
                cnt += (mask >> i) % 2;
            }

            mp[cnt]++;
        } else {
            for (int i = 0; i < m; ++i) {
                can[mask | (1 << i)] = false;
            }
        }
    }

    cout << mp.rbegin()->first << "\n" << mp.rbegin()->second;
}

signed main() {
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int tt = 1;
    while (tt--) {
        solve();
        cout << "\n";
    }
}