code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define orz %
#define ll long long
#define juruo Optimist_Skm
#define mid = (l + r) >> 1;
#define pii std::pair<int, int>
#define fi first
#define se second
namespace Fast_Skm {
template <typename T>
inline void read(T &x) {
int s = 0, w = 1;
char c = getchar();
while(!isdigit(c)) {
if(c == '-') w = -1;
c = getchar();
}
while(isdigit(c))
s = (s << 1) + (s << 3) + (c & 0xcf), c = getchar();
x = s * w;
return ;
}
template <typename T, typename... Arp>
inline void read(T &x, Arp &...arp) {
read(x), read(arp...);
return ;
}
template <typename T>
inline void write(T x) {
if(x < 0) x = -x, putchar('-');
int p = 0;
char s[100];
do {
s[++p] = x orz 10 + '0';
x /= 10;
} while (x);
while(p) putchar(s[p--]);
putchar('\n');
}
template <typename T, typename... Arp>
inline void write(T &x, Arp &...arp) {
write(x), write(arp...);
return ;
}
template <typename S, typename T>
inline void smax(S &x, T y) {
x = (x > y) ? x : y;
}
template <typename S, typename T>
inline void smin(S &x, T y) {
x = (x < y) ? x : y;
}
inline void quit() {
exit(0);
return ;
}
} using namespace Fast_Skm;
std::map<pii, int> mp;
const int N = 1e6 + 7;
int n, degree[N], m;
std::vector<int> E[N];
std::vector<int> G[N];
std::vector<int> name;
std::queue<int> Q;
int dfn[N], low[N], t = 0, st[N], tp = 0, g[N], num[N], x, NUM[N], X[N];
ll ans = 0;
inline void toposort() {
for (auto it : name) {
if(!degree[it]) {
Q.push(it), smax(ans, num[it]), X[it] = num[it];
}
}
while(!Q.empty()) {
int top = Q.front(); Q.pop();
for (auto it : G[top]) {
if (X[it] < X[top] + num[it]) {
NUM[it] = 1;
X[it] = X[top] + num[it];
}
else if (X[it] == X[top] + num[it]) {
NUM[it]++;
}
degree[it]--;
if (!degree[it]) {
Q.push(it);
smax(ans, X[it]);
}
}
}
}
inline void tarjan(int now) {
dfn[now] = low[now] = ++t;
st[++tp] = now;
for (auto it : E[now]) {
if(!dfn[it]) {
tarjan(it);
smin(low[now], low[it]);
}
else if(!g[it]) {
smin(low[now], dfn[it]);
}
}
if(low[now] == dfn[now]) {
name.emplace_back(now);
while(1) {
g[st[tp]] = now;
if(low[st[tp]] == dfn[st[tp]]) {
tp--;
break;
}
num[now] += num[st[tp]];
tp--;
}
}
return ;
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
read(n, m, x);
for (int i = 1; i <= n; ++i) {
num[i] = NUM[i] = 1;
}
for (int i = 1; i <= m; ++i) {
int u, v;
read(u, v);
E[u].emplace_back(v);
}
for (int i = 1; i <= n; ++i) {
if(!dfn[i])
tarjan(i);
//write(g[i]);
}
for (int i = 1; i <= n; ++i) {
for (auto it : E[i]) {
if(g[i] != g[it] && !mp[std::make_pair(g[i], g[it])]) {
G[g[i]].push_back(g[it]);
mp[std::make_pair(g[i], g[it])] ^= 1;
degree[g[it]]++;
}
}
}
toposort();
/*for (int i = 1; i <= n; ++i) {
write(g[i]);
}*/
ll ANS = 0;
for (auto it : name) {
if(X[it] == ans) {
ANS += NUM[it];
ANS %= x;
}
}
write(ans, ANS);
return 0;
}