#include<iostream> #include<sstream> #include<string> #include<vector> #include<list> #include<set> #include<map> #include<stack> #include<queue> #include<algorithm> #include<cmath> #pragma warning(disable:4996) using std::cin; using std::cout; using std::endl; using std::stringstream; using std::string; using std::vector; using std::list; using std::pair; using std::set; using std::multiset; using std::map; using std::multimap; using std::stack; using std::queue; using std::sort; class DisjoinSet { private: vector<int>represent, rank; public: DisjoinSet(const int &n) :represent(n), rank(n) { for (int i = 0; i < n; i++) { represent[i] = i; } } int find(int i) { return represent[i] = represent[i] == i ? i : find(represent[i]); } void merge(const int &x, const int &y) { auto a = find(x); auto b = find(y); if (rank[a] < rank[b]) { represent[a] = b; } else { represent[b] = a; if (rank[b] == rank[a]) { rank[a]++; } } } }; class Edge { public: pair<int, int>vertex; double weight; Edge(const pair<int, int>&v, const double &w) { vertex = v; weight = w; } }; bool compare(const Edge&a, const Edge&b) { if (a.weight != b.weight) { return a.weight < b.weight; } if (a.vertex.first != b.vertex.first) { return a.vertex.first < b.vertex.first; } return a.vertex.second < b.vertex.second; } vector<Edge>getEdge() { int n; if (cin >> n) { ; } else { exit(0); } vector<pair<double, double>>vertex(n); vector<vector<double>>graph(n,(vector<double>)n); for (int i = 0; i < n; i++) { cin >> vertex[i].first >> vertex[i].second; } for (int i = 0; i < n; i++) { for (int j = i+1; j < n; j++) { graph[i][j] = graph[j][i] = sqrt(pow(vertex[i].first - vertex[j].first, 2) + pow(vertex[i].second - vertex[j].second, 2)); } } cin >> n; while (n--) { int first, second; cin >> first >> second; graph[first - 1][second - 1] = graph[second - 1][first - 1] = 0.0; } vector<Edge>edge; for (int i = 0; i < vertex.size(); i++) { for (int j = i + 1; j < vertex.size(); j++) { edge.push_back({{ i,j }, graph[i][j]}); } } sort(edge.begin(), edge.end(), compare); return edge; } double kruscal(const vector<Edge>&edge) { DisjoinSet union_set((int)sqrt(edge.size() * 2) + 1); double sum = 0; int block = (int)sqrt(edge.size() * 2) + 1; for (size_t i = 0; i < edge.size(); i++) { if (union_set.find(edge[i].vertex.first) != union_set.find(edge[i].vertex.second)) { union_set.merge(edge[i].vertex.first, edge[i].vertex.second); sum += edge[i].weight; block--; if (block == 1) { return sum; } } } return 0; } int main() { //freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout); while (1) { auto edge = getEdge(); printf("%.2lf\n",kruscal(edge)); } return 0; }