#include using namespace std; #include #define rep(i, l, r) for (int i = (int)(l); i<(int)(r); i++) #define ll long long int main() { int N, M; cin >> N >> M; vector> Edges(M); rep(i, 0, M) { int u, v, c; cin >> u >> v >> c; u--; v--; c--; Edges[i] = {c, u, v}; } array cnt = {0, 0, 0, 0, 0, 0}; atcoder::dsu d(N); sort(Edges.begin(), Edges.end()); for (int i = 0; i < M; i++) { auto[c, u, v] = Edges[i]; if (!d.same(u, v)) { d.merge(u, v); cnt[c]++; } } map, double> dp; //すでにこれだけ集めたときの残り回数の期待値 array A; #define FOR(x) for (A[x] = cnt[x]; A[x] >= 0; A[x]--) FOR(0) FOR(1) FOR(2) FOR(3) FOR(4) FOR(5) { #undef FOR int loop = 0; double t = 0; rep(i, 0, 6) { //iの目が出たとする //使える中で最上位に使うのが最適 bool used = false; array B = A; for (int j = i; j >= 0; j--) { if (B[j] < cnt[j]) { B[j]++; t += dp[B]; used = true; break; } } if (!used) loop++; } if (loop == 6) { dp[A] = 0; continue; } dp[A] = (t+6)/(6-loop); } cout << fixed << setprecision(15) << dp[{0, 0, 0, 0, 0, 0}] << endl; }