#include <bits/stdc++.h>
using namespace std;
template <class T>
inline T checkmin(T &a, T b) {
  return (a < b) ? a : a = b;
}
template <class T>
inline T checkmax(T &a, T b) {
  return (a > b) ? a : a = b;
}
template <class T>
T GCD(T a, T b) {
  if (a < 0) return GCD(-a, b);
  if (b < 0) return GCD(a, -b);
  return (a == 0) ? b : GCD(b % a, a);
}
template <class T>
T LCM(T a, T b) {
  if (a < 0) return LCM(-a, b);
  if (b < 0) return LCM(a, -b);
  return (a == 0 || b == 0) ? 0 : a / GCD(a, b) * b;
}
template <class T>
T ExtGCD(T a, T b, T &x, T &y) {
  if (a < 0) {
    T c = ExtGCD(-a, b, x, y);
    x = -x;
    return c;
  }
  if (b < 0) {
    T c = ExtGCD(a, -b, x, y);
    y = -y;
    return c;
  }
  if (a == 0) {
    x = 0, y = 1;
    return b;
  } else {
    T c = ExtGCD(b % a, a, y, x);
    x -= b / a * y;
    return c;
  }
}
template <class T>
inline T sqr(T X) {
  return X * X;
}
class TUFSet {
 private:
  vector<int> S;

 public:
  TUFSet() {}
  TUFSet(int N) { S = vector<int>(N, -1); }
  int Find(int X) { return S[X] < 0 ? X : (S[X] = Find(S[X])); }
  void Union(int X, int Y) {
    X = Find(X);
    Y = Find(Y);
    if (X == Y) return;
    if (S[X] < S[Y])
      S[Y] = X;
    else {
      if (S[X] == S[Y]) --S[Y];
      S[X] = Y;
    }
  }
};
namespace Poor {
int N, M, K;
TUFSet UFS;
vector<int> D;
void Run() {
  scanf("%d%d%d", &N, &M, &K);
  UFS = TUFSet(N);
  for (int i = 0; i < M; ++i) {
    int U, V;
    scanf("%d%d", &U, &V);
    --U, --V;
    UFS.Union(U, V);
  }
  int Ans = 1 % K;
  int C = 0;
  D = vector<int>(N, 0);
  for (int i = 0; i < N; ++i) {
    ++D[UFS.Find(i)];
    if (UFS.Find(i) == i) ++C;
  }
  if (C > 1) {
    for (int i = 0; i < C - 2; ++i) Ans = ((long long)Ans * N) % K;
    for (int i = 0; i < N; ++i)
      if (D[i] > 0) Ans = ((long long)Ans * D[i]) % K;
  }
  printf("%d\n", Ans);
}
}  // namespace Poor
int main() {
  Poor::Run();
  return 0;
}
