有边权的最小生成树计数 模板
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 105; //点的个数
const int M = 1005; //边的个数
//点标从1-n
struct node {
int set[N];
void init(int n) {
for (int i = 0; i <= n; i++) set[i] = i;
}
int find(int x) {
return x == set[x] ? x : set[x] = find(set[x]);
}
int Union(int x, int y) {
int xx = find(x);
int yy = find(y);
if (xx == yy) return -1;
set[xx] = yy;
return 1;
}
}a, b, c;
struct Node {
int u, v, dis;
}edge[M];
int edgenum;
void add(int u, int v, int d){
Node E = { u, v, d };
edge[++edgenum] = E;
}
bool visit[N];
vector<int> g[N];
ll p[N][N], deg[N][N];
int cmp(Node a, Node b) {
return a.dis < b.dis;
}
ll DET(ll a[][N], int n, ll MOD)
{
int i, j, k;
ll temp = 1, t;
for (i = 0; i < n; i++) for (j = 0; j < n; j++) a[i][j] %= MOD;
for (i = 1; i < n; i++)
{
for (j = i + 1; j < n; j++) while (a[j][i])
{
t = a[i][i] / a[j][i];
for (k = i; k < n; k++)
{
a[i][k] -= a[j][k] * t;
a[i][k] %= MOD;
}
for (k = i; k < n; k++)
swap(a[i][k], a[j][k]);
temp = -temp;
}
temp = temp*a[i][i] % MOD;
}
return (temp + MOD) % MOD;
}
ll cal_MST_count(int n, ll MOD) {
sort(edge + 1, edge + edgenum + 1, cmp);
int pre = edge[1].dis;
ll ans = 1;
a.init(n);
b.init(n);
memset(visit, 0, sizeof(visit));
memset(deg, 0, sizeof(deg));
for (int i = 0; i <= n; i++) g[i].clear();
for (int t = 1; t <= edgenum + 1; t++)
{
if (edge[t].dis != pre || t == edgenum + 1)
{
for (int i = 1, k; i <= n; i++) if (visit[i])
{
k = b.find(i);
g[k].push_back(i);
visit[i] = 0;
}
for (int i = 1; i <= n; i++)
if (g[i].size())
{
memset(p, 0, sizeof(p));
for (int j = 0; j < g[i].size(); j++)
for (int k = j + 1, x, y; k < g[i].size(); k++)
{
x = g[i][j];
y = g[i][k];
p[j][k] = p[k][j] = -deg[x][y];
p[j][j] += deg[x][y];
p[k][k] += deg[x][y];
}
ans = ans*DET(p, g[i].size(), MOD) % MOD;
for (int j = 0; j < g[i].size(); j++) a.set[g[i][j]] = i;
}
memset(deg, 0, sizeof(deg));
for (int i = 1; i <= n; i++)
{
b.set[i] = a.find(i);
g[i].clear();
}
if (t == edgenum + 1) break;
pre = edge[t].dis;
}
int x = a.find(edge[t].u);
int y = a.find(edge[t].v);
if (x == y) continue;
visit[x] = visit[y] = 1;
b.Union(x, y);
deg[x][y]++;
deg[y][x]++;
}
if (!edgenum) return 0;
for (int i = 2; i <= n; i++)
if (b.find(i) != b.find(1))
return 0;
return ans;
}
void init(){ edgenum = 0; }
int n, m, u, v, d;
ll mod;
int main()
{
//freopen("in", "r", stdin);
while (cin >> n >> m >> mod, n + m + mod) {
init();
while (m--){
scanf("%d%d%d", &u, &v, &d);
add(u, v, d);
}
ll ans = cal_MST_count(n, mod);
printf("%d\n", ans%mod);
}
return 0;
}