#define _CRT_SECURE_NO_WARNINGS
#define _SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING
#include <bits/stdc++.h>
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<edge> 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;
}