#include <iostream> #include <algorithm> #include <stdio.h> #include <math.h> using namespace std; const int MAXV = 1000;//最大顶点数 const int INF = 1000000000; //n为顶点数 //MAXV为最大顶点数 int n,m; double G[MAXV][MAXV]; double d[MAXV];// 顶点到集合S的最短距离 bool vis[MAXV] = {false};//标记数组,vis[i] == true表示已访问 double prim() { fill(d,d+MAXV,INF); d[0] = 0;//只有0号顶点到集合s的距离为0,其他全为INF double ans = 0;//存放最小生成树的边权之和 //找n个点 for(int i=0;i<n;i++) { int u = -1,MIN = INF;//u使d[u]最小,MIN存放该最小的d[u] //每次找一个到集合距离最小的点 for(int j = 0;j < n;j++) { if(vis[j] == false && d[j] < MIN) { u = j; MIN = d[j]; } } if( u== -1 ) { return -1; } //标记u为已访问 vis[u] = true; ans += d[u]; for(int v=0;v < n;v++) { //如果v未访问,且u能到达v,并且以u为中转可以是v离集合更近 if(vis[v] == false && G[u][v] != INF && G[u][v] < d[v]) { d[v] = G[u][v] ; } } } return ans; } struct point { int x; int y; }; point p[MAXV]; double getDis(point &a,point &b) { return sqrt( (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); } int main() { cin >> n; for(int i=0;i<n;i++) { cin >> p[i].x; cin >> p[i].y; } //初始化图G fill(G[0],G[0] + MAXV * MAXV,INF); for(int i=0;i<m;i++) { cin >> p[i].x; cin >> p[i].y; } for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { G[i][j] = getDis(p[i],p[j]); } } double ans = prim(); printf("%.2f \n",ans); return 0; }