#include <bits/stdc++.h>
using namespace std;

const int MOD(1e9 + 7);

void dfs(vector<vector<int>>& g, int x, int y, int z, vector<bool>& used) {
    //cout << x << " " << y << " " << z << endl;
    if (used[x]) {
        return;
    }
    used[x] = true;
    for (auto i : g[x]) {
        if ((x != y) || (i != z)) {
            dfs(g, i, y, z, used);
        }
    }
}

bool dfs2(vector<vector<int>>& g3, int x, int y, vector<vector<bool>>& used) {
    if (x == y) {
        return true;
    }
    for (int i = 0; i < g3[x].size(); i++) {
        if (!used[x][i]) {
            used[x][i] = true;
            if (dfs2(g3, g3[x][i], y, used)) {
                return true;
            }
            used[x][i] = false;
        }
    }
    return false;
}

using T = pair<int, long long>;

T add(T a, T b) {
    if (a.first < b.first) {
        return a;
    } else if (b.first < a.first) {
        return b;
    }
    T ans{a.first, (a.second + b.second) % MOD};
    return ans;
}

T multiply(T a, T b) {
    T ans{a.first + b.first, (a.second * b.second) % MOD};
    return ans;
}

pair<T, T> dfs3(vector<vector<int>>& usedcyc, vector<vector<int>>& anticyc, int x, bool b, vector<bool>& used1, vector<bool>& used2) {
    vector<pair<T, T>> vecans{};
    if (b) {
        if (used2[x]) {
            return {{0, 1}, {10000, 1}};
        }
        //cout << x << "(" << b << endl;
        used2[x] = true;
        for (auto i : anticyc[x]) {
            vecans.push_back(dfs3(usedcyc, anticyc, i, false, used1, used2));
        }
        /*for (auto i : vecans) {
            cout << i.first.first << "," << i.first.second << "," << i.second.first << "," << i.second.second << endl;
        }*/
        pair<T, T> ans{{0, 1}, {1, 1}};
        for (auto i : vecans) {
            ans.first = multiply(ans.first, i.second);
            ans.second = multiply(ans.second, i.first);
        }
        ans.first = add(ans.first, ans.second);
        //cout << ans.first.first << "," << ans.first.second << "," << ans.second.first << "," << ans.second.second << endl;
        //cout << x << ")" << b << endl;
        //cout << endl;
        return ans;
    } else {
        if (used1[x]) {
            return {{0, 1}, {0, 1}};
        }
        //cout << x << "(" << b << endl;
        used1[x] = true;
        for (auto i : usedcyc[x]) {
            vecans.push_back(dfs3(usedcyc, anticyc, i, true, used1, used2));
        }
        /*for (auto i : vecans) {
            cout << i.first.first << "," << i.first.second << "," << i.second.first << "," << i.second.second << endl;
        }*/
        pair<T, T> ans{{0, 1}, {10000, 1}};
        for (int i = 0; i < vecans.size(); i++) {
            T ans2{0, 1};
            for (int j = 0; j < vecans.size(); j++) {
                if (j == i) {
                    ans2 = multiply(ans2, vecans[j].second);
                } else {
                    ans2 = multiply(ans2, vecans[j].first);
                }
            }
            ans.first = multiply(ans.first, vecans[i].first);
            ans.second = add(ans.second, ans2);
        }
        ans.first = add(ans.first, ans.second);
        //cout << ans.first.first << "," << ans.first.second << "," << ans.second.first << "," << ans.second.second << endl;
        //cout << x << ")" << b << endl;
        //cout << endl;
        return ans;
    }
}

int main() {
    int n, m, G, q, r;
    cin >> n >> m >> G;
    vector<vector<int>> g(n, vector<int>(0));
    for (int i = 0; i < m; i++) {
        cin >> q >> r;
        q--;
        r--;
        g[q].push_back(r);
    }
    vector<vector<bool>> is_bridge(n);
    vector<vector<bool>> is_connected(n, vector<bool>(n, true));
    vector<bool> used;
    for (int i = 0; i < n; i++) {
        is_bridge[i].assign(g[i].size(), false);
        for (int j = 0; j < g[i].size(); j++) {
            used.assign(n, false);
            dfs(g, i, i, g[i][j], used);
            if (!used[g[i][j]]) {
                is_bridge[i][j] = true;
            }
        }
        used.assign(n, false);
        dfs(g, i, -1, -1, used);
        for (int j = 0; j < n; j++) {
            if (!used[j]) {
                is_connected[i][j] = false;
                is_connected[j][i] = false;
            }
        }
    }
    vector<int> sccs(n, -1);
    for (int i = 0; i < n; i++) {
        if (sccs[i] == -1) {
            for (int j = 0; j < n; j++) {
                if (is_connected[i][j]) {
                    sccs[j] = i;
                }
            }
        }
    }
    int not_bridges(0), super_bridges(0);
    vector<vector<int>> g1(n, vector<int>(0));
    vector<vector<int>> g2(n, vector<int>(0));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < g[i].size(); j++) {
            //cout << i << " " << g[i][j] << " " << is_bridge[i][j] << endl;
            if ((!is_bridge[i][j]) && (sccs[i] != sccs[g[i][j]])) {
                not_bridges++;
            } else if ((is_bridge[i][j]) && (sccs[i] == sccs[g[i][j]])) {
                g2[i].push_back(g[i][j]);
            } else if ((!is_bridge[i][j]) && (sccs[i] == sccs[g[i][j]])) {
                g1[i].push_back(g[i][j]);
            }
        }
    }
    vector<vector<bool>> is_connected_2(n, vector<bool>(n, true));
    for (int i = 0; i < n; i++) {
        used.assign(n, false);
        dfs(g1, i, -1, -1, used);
        for (int j = 0; j < n; j++) {
            if (!used[j]) {
                is_connected_2[i][j] = false;
                is_connected_2[j][i] = false;
            }
        }
    }
    vector<int> sccs2(n, -1);
    for (int i = 0; i < n; i++) {
        if (sccs2[i] == -1) {
            for (int j = 0; j < n; j++) {
                if (is_connected_2[i][j]) {
                    sccs2[j] = i;
                }
            }
        }
    }
    vector<vector<int>> g3(n, vector<int>(0));
    vector<vector<bool>> used2(n, vector<bool>(0));
    vector<vector<bool>> useds(n, vector<bool>(0));
    vector<vector<int>> usedcyc{};
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < g2[i].size(); j++) {
            g3[sccs2[i]].push_back(sccs2[g2[i][j]]);
            super_bridges++;
            used2[sccs2[i]].push_back(false);
            useds[sccs2[i]].push_back(false);
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < g3[i].size(); j++) {
            if (!useds[i][j]) {
                if (dfs2(g3, g3[i][j], i, used2)) {
                    int t(0);
                    used2[i][j] = true;
                    vector<int> cyc{};
                    for (int k = 0; k < n; k++) {
                        for (int l = 0; l < g3[k].size(); l++) {
                            if (used2[k][l]) {
                                used2[k][l] = false;
                                //cout << k << " " << g3[k][l] << endl;
                                cyc.push_back(t);
                                useds[k][l] = true;
                            }
                            t++;
                        }
                    }
                    //cout << endl;
                    usedcyc.push_back(cyc);
                }
            }
        }
    }
    vector<vector<int>> anticyc(m, vector<int>(0));
    for (int i = 0; i < usedcyc.size(); i++) {
        for (auto j : usedcyc[i]) {
            anticyc[j].push_back(i);
        }
    }
    T tot_ans{0, 1};
    vector<bool> usedf1(m, false), usedf2(m, false);
    for (int i = 0; i < m; i++) {
        if (!usedf2[i]) {
            tot_ans = multiply(tot_ans, dfs3(usedcyc, anticyc, i, true, usedf1, usedf2).first);
        }
    }
    cout << not_bridges + super_bridges - tot_ans.first << endl;
    cout << tot_ans.second << endl;
}
