#define _CRT_SECURE_NO_WARNINGS #define _SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING #include using namespace std; typedef long long ll; const int N = 1e5 + 50, M = 1e6 + 50; int adj[N], nxt[M], to[M], len[M], ecnt; int fa[N]; int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); } void link(int f, int t) { fa[t] = find(f); } void addEdge(int f, int t, int w) { ecnt++; nxt[ecnt] = adj[f]; to[ecnt] = t; len[ecnt] = w; adj[f] = ecnt; } int n, m; double sum; void init(int n) { n += 10; for (int i = 0; i < n; i++) fa[i] = i; memset(adj, 0, sizeof(int) * n); sum = ecnt = 0; } struct edge { int f, t, w; }; bool operator<(const edge &lhs, const edge &rhs) { return lhs.w > rhs.w; } ll dfs(int x, int f) { ll cnt = 1; for (int e = adj[x]; e; e = nxt[e]) if (to[e] != f) { ll ccnt = dfs(to[e], x); cnt += ccnt; sum += 1.0 * ccnt * (n - ccnt) * len[e]; } return cnt; } int main() { int T; scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); init(n); priority_queue Q; for (int i = 0; i < m; i++) { int f, t, w; scanf("%d%d%d", &f, &t, &w); Q.push({f, t, w}); } ll mstsz = 0; for (int i = n; i > 1;) { auto e = Q.top(); Q.pop(); int f1 = find(e.f); int f2 = find(e.t); if (f1 != f2) { i--; mstsz += e.w; link(f1, f2); addEdge(e.f, e.t, e.w); addEdge(e.t, e.f, e.w); } } dfs(1, -1); printf("%lld %.2lf\n", mstsz, sum * 2.0 / n / (n - 1)); } return 0; }