帮公司做网站运营/关键词优化外包服务
问题描述
给定带权无向图,求出一颗方差最小的生成树。
输入格式
输入多组测试数据。第一行为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
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
Case 2: 0.00
数据规模与约定
1<=U,V<=N<=50,N-1<=M<=1000,0<=W<=50。数据不超过5组。
这题我下载出来输入的数据,有好多都是重复边。。。很难受,想不到合适的解法了,
我就直接按照不重复来做了
多次运用最小生成树(kruskal)求解
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
int father[50+5];int n,m;
double mi=10000000;
struct node{int x,y,len;double v;
};
node n1[1200];
int find(int x){if(x==father[x]) return x;return father[x]=find(father[x]);
}
bool cmp(node n1,node n2){return n1.len<n2.len;
}
bool cmp2(node n1,node n2){return n1.v<n2.v;
}
void kruskal(int sum){for(int i=1;i<=n;i++) father[i]=i;double avg=1.0*sum/(n-1);//已知sum可以求得平均值for(int i=0;i<m;i++)n1[i].v=1.0*(n1[i].len-avg)*(n1[i].len-avg);//每个边权的数-avg的平方也就能求出来sort(n1,n1+m,cmp2);//根据数-avg的平方排序double sum2=0;int sum3=0,cou=0;for(int i=0;i<m;i++){//kruskal算法int a=find(n1[i].x),b=find(n1[i].y);if(a==b) continue;father[a]=b;cou++;sum2+=n1[i].v;sum3+=n1[i].len;//每次用到的权值都相加if(cou==n-1) break;}if(sum3==sum){//要注意的是sum只是我们假设已知的,并不一定是存在的,所以要判断一下if(sum2<mi) mi=sum2;}
}
int main(){int co=0;while(cin>>n>>m){if(n==0||m==0) break; mi=10000000;for(int i=0;i<m;i++){cin>>n1[i].x>>n1[i].y>>n1[i].len;}sort(n1,n1+m,cmp);int mmin=0,mmax=0;//排序之后n-1个权值能组成的最大值和最小值for(int i=0;i<n-1;i++){mmin+=n1[i].len;}for(int i=m-1;i>m-n;i--){mmax+=n1[i].len;}for(int i=mmin;i<=mmax;i++){//假设我们已经知道了sum,就是ikruskal(i);}printf("Case %d: %.2f\n",++co,1.0*mi/(n-1));}return 0;
}
欢迎大家加入 早起学习群,一起学习一起进步!(群号:642179511)