最小方差生成树模板 BZOJ3754 Tree之最小方差树
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int MAXN = 105;
const int MAXM = 2005;
inline void read(int &num)
{
num = 0; char ch; int flag = 1;
while((ch=getchar()) < '0' || ch > '9')if(ch == '-') flag = -flag;
while(ch >= '0' && ch <= '9') num = num*10 + ch-'0', ch = getchar();
num *= flag;
}
struct node
{
int u, v; double w, val;
friend bool operator <(node x, node y)
{ return x.w < y.w; }
}E[MAXM];
int tmp[MAXM], n, m, fa[MAXN];
double Ans = 1000000000;
int find(int x) { return fa[x] == 0 ? x : fa[x] = find(fa[x]); }
void Kruskal(int k)
{
double ave = 1.0*k/(n-1);
for(int i = 1; i <= m; i++)
E[i].w = (E[i].val-ave) * (E[i].val-ave);
sort(E + 1, E + m + 1);
memset(fa, 0, sizeof fa);
double sum = 0, ans = 0;
for(int i = 1; i <= m; i++)
{
int x = find(E[i].u), y = find(E[i].v);
if(x != y)
fa[y] = x, sum += E[i].val, ans += E[i].w;
}
if(sum == k)
Ans = min(Ans, ans);
}
int main()
{
read(n), read(m);
for(int i = 1; i <= m; i++)
read(E[i].u), read(E[i].v), read(tmp[i]), E[i].val = tmp[i];
sort(tmp + 1, tmp + m + 1);
int minv = 0, maxv = 0;
for(int i = 1; i < n; i++) minv += tmp[i];
for(int i = m-n; i < m; i++) maxv += tmp[i];
for(int k = minv; k <= maxv; k++) Kruskal(k);//枚举可能的和
printf("%.4lf
", sqrt(Ans/(n-1)));//输出的是标准差
}