题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=1162
题目大意
就是给你了几个点,让你找出能把这些点连接起来的路径的最小长度
其实就是最小生成树的原理,需要使用到并查集
解题思路
把这些点存到结构体中,再用一个结构体存储边,将边长进行排序,遍历边,并将已经连接的结点使用并查集归为一类,直到遍历了n-1条边了(n为结点总数)。
具体代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define max 105
int n;
int father[max];
struct Point {
double x,y;
} p[max];
struct Edge {
double from,to,dis;
} edge[max*(max-1)/2];
double distinction(Point a,Point b) {
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(Edge a,Edge b) {
return a.dis<b.dis;
}
int find(int x) {
if(father[x]==x) return x;
return father[x]=find(father[x]);
}
void unite(int i,int j) {
int ii=find(i);
int jj=find(j);
if(ii==jj) return;
father[ii]=jj;
}
int check(int i,int j) {
if(find(i)==find(j)) return 1;
return 0;
}
double kruskal(int k) {
double sum=0;
int count=0;
for(int i=1; i<=k; i++) {
int prea=find(edge[i].from);
int preb=find(edge[i].to);
if(prea!=preb) {
sum+=edge[i].dis;
father[prea]=preb;
count++;
}
if(count==n-1){
break;
}
}
return sum;
}
int main() {
while(scanf("%d",&n)!=EOF) {
double a,b;
for(int i=0; i<n; i++) {
scanf("%lf%lf",&p[i].x,&p[i].y);
father[i]=i;
}
int k=1;
for(int i=0; i<n; i++) {
for(int j=i+1; j<n; j++) {
edge[k].from=i;
edge[k].to=j;
edge[k++].dis=distinction(p[i],p[j]);
}
}
k--;
sort(edge+1,edge+1+k,cmp);
printf("%.2lf\n",kruskal(k));
}
return 0;
}