You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
1.9 KiB
C++
89 lines
1.9 KiB
C++
#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;
|
|
} |