题目链接在这里
题目大意:
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。(直接把题目描述copy过来了。。。)
思路分析:
最小生成树!算出两点距离之后用kruskal盘它!
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#define rep(i, x) for(int i = 0; i < x; ++i)
#define clr(x) memset(x, 0, sizeof(x))
using namespace std;
const int MaxN = 105;
struct Edge{
int x, y;
double val;
bool operator < (const Edge& e) const{
return val > e.val;
}
};
struct Point{
int x, y;
}point[MaxN];
int n, t;
int par[MaxN], r[MaxN];
priority_queue<Edge> que;
void init(){
clr(r);
rep(i, MaxN) par[i] = i;
}
int Find(int x){
if(x == par[x]) return x;
return par[x] = Find(par[x]);
}
void unite(int x, int y){
x = Find(x);
y = Find(y);
if(x == y) return;
if(r[x] < r[y]) par[x] = y;
else{
par[y] = x;
if(r[x] == r[y]) ++r[x];
}
}
bool check(int x, int y){
return Find(x) == Find(y);
}
double getDis(int i, int j){
return sqrt((point[i].x - point[j].x) * (point[i].x - point[j].x) + (point[i].y - point[j].y) * (point[i].y - point[j].y));
}
void input(){
scanf("%d", &n);
rep(i, n){
scanf("%d %d", &point[i].x, &point[i].y);
}
rep(i, n){
rep(j, i){
que.push(Edge{i, j, getDis(i, j)});
//printf("i:%d, j:%d, dis:%.1f\n", i, j, getDis(i, j));
}
}
}
double kruskal(){
init();
double ans = 0.0;
while(!que.empty()){
Edge e = que.top();
que.pop();
if(check(e.x, e.y) || e.val < 10 || e.val > 1000) continue;
//printf("x:%d, y:%d\n", e.x, e.y);
ans += e.val;
unite(e.x, e.y);
}
int cnt = 0;
rep(i, n){
if(par[i] == i) ++cnt;
}
if(cnt == 1) return ans;
return -1;
}
int main(){
scanf("%d", &t);
while(t--){
input();
double ans = kruskal();
if(ans < 0)
puts("oh!");
else{
//ans *= 100;
printf("%.1lf\n", ans * 100);
}
}
return 0;
}