题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1875
题意:
在一个叫“百岛湖”的地方有 n 个小岛,政府决定要通过在岛之间建立桥使得小岛互相联通,但是距离小于10或大于1000的两个岛之间是无法建立桥的,桥的花费按照长度计费。如果能连通,那么输出最小话费,如果不能连通则输出 oh!
思路:
显然是最小生成树了,但是要注意题中给的是各岛的坐标,通过坐标算出岛之间的距离之后还要判断是否小于10或大于1000,如果是,那么两岛间无法建立桥,我们将他们之间的距离置为 INF.然后再 prim 算法中我们还要判断是否在最小生成树的总权值中加入了 n - 1 条边。如果不够我们则要输出 “oh!”,因为这证明该图是不连通的。
代码:
#include <bits/stdc++.h>
#define N 105
#define INF 1e10
#define fp(_p,_q,_r) for(int _p = _q;_p < _r;_p ++)
using namespace std;
int ro,n,co[N][2];
double cost[N][N];
double d[N];
bool used[N];
void prim(){
fill(d,d + N,INF);
fill(used,used + N,false);
d[0] = 0;
double res = 0;
fp(j,0,n){
int v = -1;
double m = INF;
fp(i,0,n){
if(!used[i] && m > d[i]) m = d[v = i];
}
if(v == -1){
printf("oh!\n");
return ;
}
used[v] = 1;
res += d[v];
fp(i,0,n) d[i] = min(d[i],cost[v][i]);
}
printf("%.1lf\n",100 * res);
}
int main(void)
{
cin >> ro;
while(ro --){
bool ok = true;
fill(cost[0],cost[0] + N * N,INF);
scanf("%d",&n);
fp(i,0,n){
scanf("%d%d",&co[i][0],&co[i][1]);
fp(j,0,i){
cost[i][j] = cost[j][i] = sqrt(pow(co[i][0] - co[j][0],2) + pow(co[i][1]-co[j][1],2));
if(cost[i][j] < 10 || cost[i][j] > 1000) cost[i][j] = cost[j][i] = INF;
}
}
prim();
}
return 0;
}