【BZOJ 3080】Minimum Variance Spanning Tree kruscal

来源:互联网 发布:人工智能与设计的未来 编辑:程序博客网 时间:2024/04/29 09:42

首先可以很显然的观察到边权值很小,所以方法就是枚举答案树的边权和,这样就可以算出平均值,然后把每一条边的的新权值就是边权减平均值的平方,然后做最小生成树,如果最小生成树的边权和等于枚举的边权和就用当前答案来更新最终的答案。因为每一个权值和都会枚举到,所以一定会枚举到答案的总边权和,所以一定会更新答案。

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define maxn 2021using namespace std;int n,m,f[maxn];double Ans=1e9;struct  edge{int a,b,v;double c;bool operator<(const edge& y)const{return c<y.c;}}e[maxn],a[maxn];int find(int x){return f[x]==x ? x : f[x]=find(f[x]);}void solve(int y){double ans=0;for(int i=1;i<=n;i++)f[i]=i;sort(e+1,e+1+m);int all=0;for(int i=1;i<=m;i++){int dx=find(e[i].a),dy=find(e[i].b);if(dx!=dy){y-=e[i].v;f[dx]=dy;ans+=e[i].c;}}if(!y)Ans=min(Ans,ans/(n-1));}int main(){int cs=0;while(scanf("%d%d",&n,&m)&&n+m){int Mx=0,Mi=0;Ans=1e9;for(int i=1;i<=m;i++){scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].v);a[i].c=a[i].v;}sort(a+1,a+1+m);for(int i=1;i<n;i++)Mi+=a[i].c;for(int i=1;i<n;i++)Mx+=a[m-i+1].c;double x;for(int i=Mi;i<=Mx;i++){x=i*1.0/(n-1);for(int j=1;j<=m;j++){e[j]=a[j];e[j].c=(a[j].v-x)*(a[j].v-x);}solve(i);}printf("Case %d: %.2lf\n",++cs,Ans);}return 0;}


0 0
原创粉丝点击