#include <bits/stdc++.h>
using namespace std;
const int MAXN = 650;
int kd[MAXN], edges[100010][2];
int idA[MAXN], idB[MAXN];
int g[MAXN][MAXN];
int P;
inline int advPow(int a, int b) {
  int ret = 1;
  while (b) {
    if (b & 1) ret = (long long)ret * a % P;
    a = (long long)a * a % P;
    b >>= 1;
  }
  return ret;
}
inline int inverse(int a) { return advPow(a, P - 2); }
int gauss(int N) {
  int ret = 1;
  for (int col = 1; col <= N; col++) {
    int pos = 0;
    for (int row = col; row <= N; row++)
      if (g[row][col]) {
        pos = row;
        break;
      }
    if (pos && pos != col) {
      for (int i = 1; i <= N; i++) swap(g[pos][i], g[col][i]);
      ret *= -1;
    }
    if (pos == 0) return 0;
    int inv = inverse(g[col][col]);
    for (int row = 1; row <= N; row++) {
      if (!g[row][col] || row == col) continue;
      int cur = (long long)g[row][col] * inv % P;
      for (int i = col; i <= N; i++)
        g[row][i] = (g[row][i] - (long long)g[col][i] * cur % P + P) % P;
    }
  }
  for (int i = 1; i <= N; i++) ret = (long long)ret * g[i][i] % P;
  return (ret + P) % P;
}
struct Node {
  int v, nxt;
} d[100010];
int head[MAXN], etot;
inline void addEdge(int a, int b) {
  etot++;
  d[etot].v = b;
  d[etot].nxt = head[a];
  head[a] = etot;
}
int rin[MAXN], rout[MAXN];
int plans[MAXN][MAXN];
queue<int> que;
int main() {
  int N, M;
  scanf("%d%d%d", &N, &M, &P);
  for (int i = 1; i <= M; i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    if (a == b) continue;
    rin[b]++, rout[a]++;
    addEdge(a, b);
  }
  for (int i = 1; i <= N; i++)
    if (!rin[i]) que.push(i);
  for (int i = 1; i <= N; i++) plans[i][i] = 1;
  int cnt1 = 0, cnt2 = 0;
  for (int i = 1; i <= N; i++)
    if (!rin[i]) idA[++cnt1] = i;
  for (int i = 1; i <= N; i++)
    if (!rout[i]) idB[++cnt2] = i;
  if (cnt1 != cnt2) {
    puts("0");
    return 0;
  }
  while (!que.empty()) {
    int u = que.front();
    que.pop();
    for (int e = head[u]; e; e = d[e].nxt) {
      rin[d[e].v]--;
      for (int i = 1; i <= N; i++) (plans[i][d[e].v] += plans[i][u]) %= P;
      if (!rin[d[e].v]) que.push(d[e].v);
    }
  }
  for (int i = 1; i <= cnt1; i++)
    for (int j = 1; j <= cnt2; j++) g[i][j] = plans[idA[i]][idB[j]];
  printf("%d\n", gauss(cnt1));
}
