题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1875
题目大意:中文题
分析:这题,就是附加了条件的最小生成树,要求最小生成树上的权大于等于10,小于等于1000,问能不能找到这样一棵生成树,以及生成树的权之和。如果我们直接贴最小生成树的板子,那么当两个点的最段距离<10,该如何pass掉,然后找他们的次短距离,如果还不满足,依次类推。那么我们不妨在处理点与点之间的距离时处理一下,让不满足条件的距离等于INF,那么使用最小生成树算法时自然不会选到长为INF的边,如果选到了,说明没有满足条件的生成树。
code:
#include<cstdio>
#include<cmath>
#define min(a,b) (a<b?a:b)
const int MAXV=100+5,INF=999999;
double mincost[MAXV];
bool used[MAXV];
int x[MAXV],y[MAXV];
double cost[MAXV][MAXV];
int V;
double dist(double x1,double y1,double x2,double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double prim(){
for(int i=1;i<=V;++i)
mincost[i]=INF,used[i]=false;
mincost[1]=0.0;
double res=0.0;
while(true){
int v=-1;
for(int u=1;u<=V;++u){
if(!used[u]&&(v==-1||mincost[u]<mincost[v]))v=u;
}
if(v==-1)break;
used[v]=true;
res+=mincost[v];
for(int u=1;u<=V;++u){
mincost[u]=min(mincost[u],cost[v][u]);
}
}
return res;
}
int main(void){
int T;scanf("%d",&T);
while(T--){
scanf("%d",&V);
for(int i=1;i<=V;++i)
scanf("%d%d",&x[i],&y[i]);
for(int i=1;i<=V;++i)
for(int j=1;j<=i;++j){
double temp=dist((double)x[i],(double)y[i],(double)x[j],(double)y[j]);
cost[i][j]=cost[j][i]= (temp>=10&&temp<=1000?temp:INF);
}
double distance=prim();
if(distance>=INF)printf("oh!\n");
else{
double cost=100*distance;
printf("%.1lf\n",cost);
}
}
}