#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,P;
vector<int> ljb[605];
vector<int> G[605];
vector<int> nr;
vector<int> nc;
int cnt;
int rd[605];
int cd[605];
int power(int x,int y=P-2){
if(y==0)return 1;
int tmp=power(x,y>>1);
if(y&1)return tmp*tmp%P*x%P;
else return tmp*tmp%P;
}
int dp[605][605];
void toposort(){
queue<int> q;
for(int i=0;i<nc.size();i++){
dp[nc[i]][i]=1;
q.push(nc[i]);
}
while(!q.empty()){
int tmp=q.front();
q.pop();
for(int j=0;j<nc.size();j++){
for(int i=0;i<ljb[tmp].size();i++){
int v=ljb[tmp][i];
dp[tmp][j]+=dp[v][j];
dp[tmp][j]%=P;
}
}
for(int i=0;i<G[tmp].size();i++){
int v=G[tmp][i];
cd[v]--;
if(!cd[v]){
q.push(v);
}
}
}
return;
}
int S[605][605];
int solve(int n){
int ans=1;
for(int i=0;i<n;i++){
int maxi=i;
for(int j=i+1;j<n;j++){
if(S[j][i]>S[maxi][i])maxi=j;
}
if(!S[maxi][i]){
return 0;
}
if(maxi^i)ans=-ans;
swap(S[maxi],S[i]);
ans*=S[i][i];
ans%=P;
ans+=P;
ans%=P;
for(int j=i+1;j<n;j++){
int dt=S[j][i]*power(S[i][i])%P;
for(int k=i;k<n;k++){
S[j][k]-=dt*S[i][k]%P;
S[j][k]%=P;
S[j][k]+=P;
S[j][k]%=P;
}
}
}
return ans;
}
signed main(){
scanf("%lld%lld%lld",&n,&m,&P);
for(int i=1;i<=m;i++){
int u,v;
scanf("%lld%lld",&u,&v);
ljb[u].push_back(v);
G[v].push_back(u);
rd[v]++;
cd[u]++;
}
for(int i=1;i<=n;i++){
if(rd[i]==0){
nr.push_back(i);
}
if(cd[i]==0){
nc.push_back(i);
}
}
toposort();
cnt=nr.size();
for(int i=0;i<cnt;i++){
int u=nr[i];
for(int j=0;j<cnt;j++){
S[i][j]=dp[u][j];
}
}
//然后算S的行列式
printf("%lld\n",solve(cnt));
return 0;
}
/*
对于汇点建反向边。
*/
根据我的计算,她的时间复杂度绝对不会爆炸!
拓扑排序,总共要扫 n 个点和 m 条边,每次最多就 2n 个点可能有用,抹去常数就是一个 O(n(n+m)) 的算法,为啥会挂掉呢?