显示代码纯文本
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MOD = 31011;
const int MAXN = 110;
const int MAXM = 1010;
struct edge {
int u, v, d;
inline bool operator<(edge rhs) const {
return d < rhs.d;
}
} E[MAXM];
int Ans = 1, N, M;
struct FUS {
int set[MAXN];
int find(int u) {
return (set[u] == u) ? u : (set[u] = find(set[u]));
}
bool join(int u, int v) {
int pu = find(u), pv = find(v);
if(pu != pv) set[pu] = pv;
return pu != pv;
}
void init() {
for(int i = 1; i <= N; i++) set[i] = i;
}
int count() {
int ans = 0;
for(int i = 1; i <= N; i++) if(set[i] == i) ans++;
return ans;
}
} setL, setN, setR;
int main() {
freopen("bzoj_1016.in", "rt", stdin);
freopen("bzoj_1016.out", "wt", stdout);
int i, k, u, v;
scanf("%d%d", &N, &M);
for(i=0;i<M;i++) scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].d);
sort(E, E + M);
//bf
setL.init(); setR.init();
int begin = 0, set, len, s, cnt;
for(k=0;k<M;k++) if(k == M - 1 || (E[k].d != E[k+1].d)) {
//calc right value
for(i=begin;i<=k;i++) setR.join(E[i].u, E[i].v);
//bf cur state
len = k - begin + 1; cnt = 0;
for(set=0;set<(1 << len);set++) {
bool ok = 1;
for(i=1;i<=N;i++) setN.set[i] = setL.set[i];
for(s=0;s<len;s++) if((set >> s) & 1) {
u = E[begin + s].u; v = E[begin + s].v;
if(!setN.join(u, v)) {
ok = 0; break;
}
}
if(ok) {
if(setN.count() != setR.count()) ok = 0;
}
cnt += ok;
}
Ans = (Ans * cnt) % MOD;
//update MST
//Run Kruskal
for(i=1;i<=N;i++) setL.set[i] = setR.set[i];
begin = k + 1;
}
//Check
k = 0;
for(i=1;i<=N;i++) {
u = setR.find(i);
if(k && k != u) Ans = 0;
else k = u;
}
printf("%d", Ans);
}