最小方差生成树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ike940067893/article/details/83215556

最小方差生成树模板 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\n", sqrt(Ans/(n-1)));//输出的是标准差
}

猜你喜欢

转载自blog.csdn.net/Ike940067893/article/details/83215556