# [Bzoj1016][JSOI2008]最小生成树计数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 6e6 + 10;
const int mod = 31011;
struct node {
int s, e, w;
}q[maxn];
struct qujian {
int l, r, val;
}a[maxn];
int fa[maxn];
int Find(int x) {
return x == fa[x] ? fa[x] : Find(fa[x]);
}
bool cmp(node a, node b) {
return a.w < b.w;
}
int sum;
void dfs(int x, int now, int k) {
if (now == a[x].r + 1) {
if (k == a[x].val)
sum++;
return;
}
int xx = Find(q[now].s);
int yy = Find(q[now].e);
if (xx != yy) {
fa[xx] = yy;
dfs(x, now + 1, k + 1);
fa[xx] = xx, fa[yy] = yy;
}
dfs(x, now + 1, k);
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)fa[i] = i;
for (int i = 1; i <= m; i++)
scanf("%d%d%d", &q[i].s, &q[i].e, &q[i].w);
sort(q + 1, q + 1 + m, cmp);
int cnt = 1, num = 0, ans = 1;
for (int i = 1; i <= m; i++) {
if (q[i].w != q[i - 1].w) {
a[cnt++].r = i - 1;
a[cnt].l = i;
}
int xx = Find(q[i].s);
int yy = Find(q[i].e);
if (xx != yy) {
a[cnt].val++;
fa[xx] = yy;
num++;
}
}
if (num != n - 1) {
printf("0");
return 0;
}
a[cnt].r = m;
for (int i = 1; i <= n; i++)
fa[i] = i;
for (int i = 1; i <= cnt; i++) {
sum = 0;
dfs(i, a[i].l, 0);
ans = ans * sum % mod;
for (int j = a[i].l; j <= a[i].r; j++) {
int xx = Find(q[j].s);
int yy = Find(q[j].e);
if (xx != yy)
fa[xx] = yy;
}
}
printf("%d\n", ans);
}

posted @ 2019-07-03 13:56  祈梦生  阅读(58)  评论(0编辑  收藏