题目描述:
给定平面上N个城市的位置,计算连接这N个城市所需线路长度总和的最小值。
输入描述:
输入文件中包含多个测试数据。每个测试数据的第1行为一个正整数N,0《=N《=100,代表需要连接的城市数目;接下来有N行,每行为两个实数X和Y,-10000《=X,Y《=10000,表示每个城市的X坐标和Y坐标。输入文件中最后一行为N=0,代表输入结束。
输出描述:
对输入文件中每个测试数据,计算连接所有城市所需线路长度总和的最小值。每对城市之间的线路为连接这两个城市的直线。对于求得的值精确到小数点后两位有效数字。
代码:
kryskal算法:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std ;
int m , n ;
double x[101], y[101], ans;
int pre[5000];
typedef struct
{
int x,y;
double w;
}node;
node edge[5000];
int cmp(node a, node b) //从小到大排序
{
return a.w<b.w;
}
int find(int t) //递归找到其 父节点,即当前顶点属于哪个集合
{
return t==pre[t] ? t:find(pre[t]) ;
}
void hebing(int x,int y) //两个不同集合的合并,将y的父节点更新为x;即把两棵树合并为一颗
{
pre[y]=x ;
}
void Kruskal()
{
int i,j,x1,x2;
for( i = 0 ; i < n;i++) //初始化,设定 每个顶点都为一个独立的集合,父节点是自己本身
pre[i]=i ;
for( i = 0 ; i<m ; i++ )
{
x1=find(edge[i].x);
x2=find(edge[i].y);
if(x1!=x2) //a==b说明边的两个顶点一属于同一颗树, //将a的父节点更新为b,从而将树a,b合并成一棵树
{
hebing(x1,x2);
ans += edge[i].w; //将边的权值加到ans当中
}
}
}
int main()
{
int T = 0;
while(scanf("%d", &n), n) {
ans = 0;
for(int i = 0; i < n; i++) {
scanf("%lf %lf", &x[i], &y[i]);
}
m = 0;ans=0;
for(int i = 0; i < n; i++) {
for(int j = i+1; j < n; j++) {
edge[m].x = i;
edge[m].y = j;
edge[m].w = sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
m++;
}
}
sort(edge,edge+m,cmp);
Kruskal();
if( T ) printf("\n");
printf("Case #%d:\n", ++T);
printf("The minimal distance is: %.2lf\n", ans);
}
return 0;
}
Prim算法: