#include <algorithm> #include <iostream> #include <cstdio> #include <cmath> #include <math.h> using namespace std; #define MAXN 105 #define MAXM 5050 double X[MAXN],Y[MAXN];//用来存储x,y的坐标,其他关于坐标的运算可以模仿 int i,n,j,m,mi,x,y;//循环变量,frist i defined it in main() double sum=0.0;//总权值 struct edge { int u,v;//顶点 double w;//权值,注意类型 }edges[MAXN]; int parent[MAXN]; int cmp(const void *a,const void *b) { // return (*(edge *))我想用另种方法 edge aa=*(const edge *)a;edge bb=*(const edge *)b; if (aa.w>bb.w) return 1; else return -1; } void UFset()//初始化 { for(i=0;i<=mi;i++) parent[i]=-1; } int Find(int x)//查找并返回节点x所属集合的根节点 { int s=x; for(;parent[s]>=0;s=parent[s]) ; while(s!=x)//优化方案——压缩路径,使后续查找更加方便,但为什么呢 { parent[x]=s; x=s; } return s; } void Union(int R1,int R2) { int r1=Find(R1),r2=Find(R2);// r1,r2分别为根节点 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 num=0; //int u,v; UFset(); for(i=0;i<mi;i++) { x=edges[i].u;y=edges[i].v; if(Find(x)!=Find(y)) { //printf("%d %d",x,y); sum+=edges[i].w; num++; Union(x,y); } if(num>=n-1) break; } } int main() { // freopen("in.txt","r",stdin); // int n;//测试数据的个数 double d;//可以不要了 //int m=0,mi;//边的标志,中间变量 int kcase=1; while(1) { cin>>n; if(n==0) break; //输入各个城市的坐标 for(i=0;i<n;i++) scanf("%lf%lf",&X[i],&Y[i]);//这一句关键去了,没有%lf不读数据 int m=0; for(i=0;i<n;i++) { for(j=i+1;j<n;j++) { //scanf("%f%f",&x,&y);自己第一次写的 //两点之间的距离 d=sqrt((X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j])); edges[m].u=i; edges[m].v=j; edges[m].w=d; m++; } } mi=m;//我先自己试试,还是用这个吧,比较好用 qsort(edges,mi,sizeof(edges[0]),cmp); sum=0.0; kruskal(); // for(i=0;i<mi;i++) // printf("%d-->%d=%0.2f\n",edges[i].u,edges[i].v,edges[i].w); if(kcase>1) cout<<endl; printf("Case #%d:\n",kcase); printf("The minimal distance is: %0.2f\n",sum); kcase++; } return 0; }
原文:http://blog.csdn.net/yuzibo747/article/details/19019001