您的位置:首页 > 其它

BZOJ 3754 Tree之最小方差树 解题报告

2014-11-26 20:25 253 查看
<span style="font-family: arial, verdana, helvetica, sans-serif; font-size: 18px; background-color: rgb(228, 240, 248);">题目大意就是要求一个图的最小方差生成树</span>
<span style="font-family: arial, verdana, helvetica, sans-serif; font-size: 18px; background-color: rgb(228, 240, 248);">点数<=100, 边数<=2000, 1<=边权<=100且为整数</span>


-----------------------------------------------华丽的分割线--------------------------------------------------

My code:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 100 + 5
#define M 2000 + 5
#define eps 1e-9

int n, m, Fa
, W[M], Ord[M];
double ave, ans = 1e9;

struct Edge
{
int u, v;
double c;
Edge(int _u = 0, int _v = 0, double _c = 0.0) {u = _u, v = _v, c = _c;}
bool operator < (const Edge a) const {return c < a.c;}
}E[M];

inline int Find(int x)
{
return x == Fa[x] ? x : Fa[x] = Find(Fa[x]);
}

inline double MST(int s, int delta)
{
for (int i = 1; i <= n; i ++)
Fa[i] = i;
double sum = 0;
for (int i = s, cnt = 1; i && i <= m && cnt < n; i += delta)
{
int t = Ord[i], u = Find(E[t].u), v = Find(E[t].v);
if (u != v)
{
cnt ++;
sum += E[t].c;
Fa[u] = v;
}
}
return sum;
}

inline bool cmp(int u, int v)
{
return E[u].c < E[v].c && abs(E[u].c - E[v].c) > eps;
}

inline double Solve(int sum)
{
ave = (double) sum / (n - 1);
for (int i = 1; i <= m; i ++)
E[i].c = (ave - W[i]) * (ave - W[i]);
sort(Ord + 1, Ord + m + 1, cmp);
return sqrt(MST(1, 1) / (n - 1));
}

int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i ++)
{
int u, v;
scanf("%d%d%d", &u, &v, W + i);
E[i] = Edge(u, v, (double) W[i]);
Ord[i] = i;
}
sort(Ord + 1, Ord + m + 1, cmp);
int Min = (int) MST(1, 1);
int Max = (int) MST(m, -1);
for (int i = Min; i <= Max; i ++)
{
double t = Solve(i);
ans = min(ans, t);
}
printf("%.4lf\n", ans);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: