Zhang_Wenjie @ 2024-07-27 22:33:21
#include <bits/stdc++.h>
#define re register int
using namespace std;
const int N = 1e5 + 10, M = 1e6 + 10;
struct Edge
{
int to, next;
}e[M];
int top, h[N];
int dfn[N], low[N], idx, scc[N], siz[N], cnt;
int in[N], f[N], g[N];
int n, m, mod, ax[N], ay[N];
bool st[N], used[N];
stack<int> stk;
vector<int> v[N];
inline void add(int x, int y)
{
e[++ top] = (Edge){y, h[x]};
h[x] = top;
}
void tarjan(int u)
{
dfn[u] = low[u] = ++ idx;
st[u] = true;
stk.push(u);
for (re i = h[u]; i; i = e[i].next)
{
int v = e[i].to;
if (!dfn[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (st[v])
low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u])
{
cnt ++;
int ver;
do
{
ver = stk.top(); stk.pop();
st[ver] = false;
scc[ver] = cnt;
siz[cnt] ++;
}while (ver != u);
}
}
inline void topsort()
{
queue<int> q;
for (re i = 1; i <= cnt; i ++)
{
f[i] = siz[i];
g[i] = 1;
if (in[i] == 0) q.push(i);
}
while (!q.empty())
{
int x = q.front(); q.pop();
for (re i = 0; i < v[x].size(); i ++)
{
int y = v[x][i];
if (used[y] == x) continue;
used[y] = x;
if (f[x] + siz[y] > f[y])
{
f[y] = f[x] + siz[y];
g[y] = g[x];
}
else if (f[x] + siz[y] == f[y])
g[y] = (g[y] + g[x]) % mod;
if (-- in[y] == 0)
q.push(y);
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m >> mod;
for (re i = 1; i <= m; i ++)
{
cin >> ax[i] >> ay[i];
add(ax[i], ay[i]);
}
for (re i = 1; i <= n; i ++)
if (!dfn[i]) tarjan(i);
for (re i = 1; i <= m; i ++)
if (scc[ax[i]] != scc[ay[i]])
{
v[scc[ax[i]]].push_back(scc[ay[i]]);
in[scc[ay[i]]] ++;
}
topsort();
int mx = 0, sum = 0;
for (re i = 1; i <= cnt; i ++) mx = max(mx, f[i]);
for (re i = 1; i <= cnt; i ++)
if (f[i] == mx) sum = (sum + g[i]) % mod;
cout << mx << '\n' << sum << '\n';
return 0;
}