Freckles【北京大学复试机试题】【Kruskal】
题目描述
In an episode of the Dick Van Dyke show, little Richie connects the freckles on his Dad's back to form a picture of the Liberty Bell. Alas, one of the freckles turns out to be a scar, so his Ripley's engagement falls through. Consider Dick's back to be a plane with freckles at various (x,y) locations. Your job is to tell Richie how to connect the dots so as to minimize the amount of ink used. Richie connects the dots by drawing straight lines between pairs, possibly lifting the pen between lines. When Richie is done there must be a sequence of connected lines from any freckle to any other freckle.
输入描述:
The first line contains 0 < n <= 100, the number of freckles on Dick's back. For each freckle, a line follows; each following line contains two real numbers indicating the (x,y) coordinates of the freckle.
输出描述:
Your program prints a single real number to two decimal places: the minimum total length of ink lines that can connect all the freckles.
示例1
输入
3 1.0 1.0 2.0 2.0 2.0 4.0
输出
3.41
题意:输入n,表示有n个点,接下来的n行输入n个点的位置。输出能将所有点连起来的最小长度,就是一个最小生成树的问题
思路:n个点有n*(n-1)/2条边,将这些边按照大小顺序排序,用Kurskal求最小生成树。这道题也是,数据结构比较复杂。
注意:需要注意的一点是,如果要用map,并且map的键为结构体类型,必须要对这个结构体重载小于号,因为map是自动排序的。
#include<iostream>
#include<algorithm>
#include<map>
#include<cmath>
using namespace std;
const int MAXN=101;
struct Point{
double x;
double y;
bool operator< (Point a) const{ //因为用了map<Point,Point>,而map会自动排序所以必须要进行小于运算符的重载
if(x==a.x){
return y<a.y;
}
else{
return x<a.x;
}
}
}points[MAXN];
struct edge{
Point from;
Point to;
double len;
bool operator < (edge a) const{
return len<a.len;
}
}edges[100000];
map<Point,Point> father;
map<Point,int> height;
void Init(int n){
for(int i=0;i<n;i++){
father[points[i]]=points[i];
height[points[i]]=0;
}
}
Point Find(Point p){
if(p.x!=father[p].x||p.y!=father[p].y ){
father[p]=Find(father[p]);
}
return father[p];
}
void Union(Point i,Point j){
i=Find(i);
j=Find(j);
if(i.x!=j.x||i.y!=j.y ){
if(height[i]>height[j]){
father[j]=i;
}
else if(height[j]>height[i]){
father[i]=j;
}
else{
father[j]=i;
height[i]++;
}
}
return ;
}
double Kruskal(int n,int edgenumber){
Init(n);
double sum=0;
sort(edges,edges+edgenumber);
for(int i=0;i<edgenumber;i++){
//若不在同一集合,则合并
if(Find(edges[i].from).x!=Find(edges[i].to).x || Find(edges[i].from).y!=Find(edges[i].to).y){
Union(edges[i].from,edges[i].to);
sum+=edges[i].len;
}
}
return sum;
}
int main(){
int n;
scanf("%d",&n);
int x,y;
for(int i=0;i<n;i++){
scanf("%lf%lf",&points[i].x,&points[i].y);
}
int m=n*(n-1)/2;
int k=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
double l=(points[i].x-points[j].x)*(points[i].x-points[j].x)+(points[i].y-points[j].y)*(points[i].y-points[j].y);
edge temp;
temp.from=points[i];
temp.to=points[j];
temp.len=sqrt(l);
edges[k++]=temp;
}
}
printf("%.2lf\n",Kruskal(n,k));
return 0;
}
本文地址:https://blog.csdn.net/han_hhh/article/details/107340417