容斥一下然后生成树计数就行了....
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 105; int a[maxn][maxn]; LL c[maxn][maxn]; int base, n, m, q; int det(int n) { int ans = 1, i, j, k; bool flag = true; for (i = 1; i < n; i++) for (j = 1; j < n; j++) a[i][j] = (a[i][j] + base) % base; for (i = 1; i < n; i++) { for (j = i + 1; j < n; j++) while (a[j][i]) { int t = a[i][i] / a[j][i]; for (k = i; k < n; k++) a[i][k] = (a[i][k] + base - (LL)t * (LL)a[j][k] % base) % base; for (k = i; k < n; k++) swap(a[i][k], a[j][k]); flag ^= true; } ans = (LL)ans * (LL)a[i][i] % base; if (!ans) return 0; } if (!flag) ans = (base - ans); return ans; } void init() { int N = 100; c[0][0] = 1 % base; for(int i = 1; i <= N; i++) { c[i][0] = 1 % base; for(int j = 1; j <= i; j++) c[i][j] = (c[i-1][j] + c[i-1][j-1]) % base; } } LL powmod(LL a, LL b) { LL res = 1, BASE = a; while(b) { if(b % 2) res = res * BASE % base; BASE = BASE * BASE % base; b /= 2; } return res; } void work() { scanf("%d%d%d%d", &n, &m, &base, &q); init(); memset(a, 0, sizeof a); for(int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); a[u][v]--, a[v][u]--; a[u][u]++, a[v][v]++; } int res = det(n); LL cnt = powmod(n-1, q); for(int i = 1; i <= n-1; i++) { if(i & 1) cnt = (cnt - c[n-1][i] * powmod(n-1-i, q) % base) % base; else cnt = (cnt + c[n-1][i] * powmod(n-1-i, q) % base) % base; } LL ans = cnt * res % base; ans = (ans % base + base) % base; printf("%lld\n", ans); } int main() { //freopen("data", "r", stdin); int _; scanf("%d", &_); while(_--) work(); return 0; }