算法提高 最小方差生成树
2018-02-04 20:47
381 查看
问题描述
给定带权无向图,求出一颗方差最小的生成树。
输入格式
输入多组测试数据。第一行为N,M,依次是点数和边数。接下来M行,每行三个整数U,V,W,代表连接U,V的边,和权值W。保证图连通。n=m=0标志着测试文件的结束。
输出格式
对于每组数据,输出最小方差,四舍五入到0.01。输出格式按照样例。
样例输入
4 5
1 2 1
2 3 2
3 4 2
4 1 1
2 4 3
4 6
1 2 1
2 3 2
3 4 3
4 1 1
2 4 3
1 3 3
0 0
样例输出
Case 1: 0.22
Case 2: 0.00
数据规模与约定
1<=U,V<=N<=50,N-1<=M<=1000,0<=W<=50。数据不超过5组。
蓝桥杯的OJ测试数据好像有问题,只能得50分。
这题可以用暴力枚举把所有边权值的和的可能全部列出来,然后对每一个可能求均值。对每一次的可能跑一次Kruskal,设一个新权值为方差×(n-1)。如果一次Kruskal后的边权和等于枚举的值,那么更新新权值的(比较大小,取小的)。
给定带权无向图,求出一颗方差最小的生成树。
输入格式
输入多组测试数据。第一行为N,M,依次是点数和边数。接下来M行,每行三个整数U,V,W,代表连接U,V的边,和权值W。保证图连通。n=m=0标志着测试文件的结束。
输出格式
对于每组数据,输出最小方差,四舍五入到0.01。输出格式按照样例。
样例输入
4 5
1 2 1
2 3 2
3 4 2
4 1 1
2 4 3
4 6
1 2 1
2 3 2
3 4 3
4 1 1
2 4 3
1 3 3
0 0
样例输出
Case 1: 0.22
Case 2: 0.00
数据规模与约定
1<=U,V<=N<=50,N-1<=M<=1000,0<=W<=50。数据不超过5组。
蓝桥杯的OJ测试数据好像有问题,只能得50分。
这题可以用暴力枚举把所有边权值的和的可能全部列出来,然后对每一个可能求均值。对每一次的可能跑一次Kruskal,设一个新权值为方差×(n-1)。如果一次Kruskal后的边权和等于枚举的值,那么更新新权值的(比较大小,取小的)。
#include<bits/stdc++.h> using namespace std; #define MAX 100100 #define min(a,b) (a<b)? a:b typedef struct Edge{ int U,V; double W, value;//方差权重 //Edge(int U=0,int V=0,double W=0,double value=0):U(U),V(V),W(W),value(value){} }Edge; Edge F[MAX]; int parent[MAX]; int tmp[MAX]; double ans; int N,M; int cmp(Edge a,Edge b){ return a.value<b.value; } int Find(int x){ int s; for(s=x;parent[s]>=0;s=parent[s]); while(s!=x) { int tmp=parent[x]; parent[x]=s; x=tmp; } return s; } /*int getfather(int x) { return parent[x]==x ? x: parent[x]=getfather(parent[x]); }*/ void Union(int S,int E){ int r1=Find(S),r2=Find(E); int tmp=parent[r1]+parent[r2]; if(parent[r1]>parent[r2]) { parent[r1]=r2; parent[r2]=tmp; } else { parent[r2]=r1; parent[r1]=tmp; } } void Kruskal(int sum){ int U,V; int count=0; double sumweight=0; double tmp_ans=0; double ave=sum*1.0/(N-1); for(int i=0;i<M;i++) F[i].value=(F[i].W-ave)*(F[i].W-ave); for(int i=1;i<=N;i++) parent[i]=-1; sort(F,F+M,cmp); for(int i=0;i<M;i++) { U=F[i].U; V=F[i].V; //int t1=Find(F[i].U); //int t2=Find(F[i].V); if(Find(U)!=Find(V))//t1!=t2) { // parent[t1]=t2; sumweight+=F[i].W; tmp_ans+=F[i].value; Union(U,V); count++; if(count >= N-1) break; } } if((int)sumweight==sum){ ans=min(ans,tmp_ans); } } int main(){ int cas=1; while(~scanf("%d%d",&N,&M),N+M){ int max=0,min=0; ans=9999999999.00; for(int i=0;i<M;i++){ cin>>F[i].U>>F[i].V>>F[i].W; tmp[i]=F[i].W; } sort(tmp,tmp+M); for(int i=0;i<N-1;i++) min+=tmp[i]; for(int i=M-1;i>M-N;--i) max+=tmp[i]; for(int i=min;i<=max;i++) Kruskal(i); ans=ans/(N-1); cout<<"Case "<<cas++<<": "; cout<<fixed<<setprecision(2)<<ans<<endl; } return 0; }
相关文章推荐
- 算法提高 最小方差生成树
- 【 算法提高 最小方差生成树 】(MST,据说。。 没对)
- 算法笔记_164:算法提高 最小方差生成树(Java)
- 蓝桥杯_算法提高_最小方差生成树(Kruskal算法)
- 蓝桥杯——算法提高 最小方差生成树
- 算法提高 最小方差生成树(Kruskal)_模板
- 算法提高 最小方差生成树 (kruskal)
- 算法提高 最小方差生成树
- 算法提高 最小方差生成树
- 一些竞赛算法题目及解答(角谷步数,数组非排序正负数分离, 最小方差生成树)
- Prim 算法求最小生成树 O(n^2)
- 最小生成树算法之Prim算法
- 最小生成树的两种算法
- 【算法】图的最小生成树(Kruskal算法)
- 【无浪】无向图论_最小生成树三种算法
- 图的基本算法(最小生成树)
- 关于最小生成树中的 Kruskal(克鲁斯卡尔)算法
- 邻接表存储 - Kruskal最小生成树算法
- 最小生成树之克鲁斯卡尔(Kruskal)算法实现,代码详解!!!!
- 数据结构_7:图算法 :图的最小生成树