题目大意是给一些点,这些点两两之间有距离,有代价。请你找出一个最小生成树,
使代价/距离最小。
最优比率生成树问题。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int VM=1010;
const double INF=1e15;
const double eps=1e-5;
struct node{
double x,y,z;
}e[VM];
double dist[VM][VM],cost[VM][VM],map[VM][VM],dis[VM];
int path[VM],n,vis[VM];
double Prim(double ratio){
int i,j;
for(i=1;i<=n;i++){
map[i][i]=0;
for(j=i+1;j<=n;j++)
map[i][j]=map[j][i]=cost[i][j]-ratio*dist[i][j];
}
for(i=1;i<=n;i++){
dis[i]=map[1][i];
vis[i]=0;
path[i]=1;
}
dis[1]=0;
vis[1]=1;
int k;
for(i=1;i<n;i++){
double tmp=INF;
for(j=1;j<=n;j++)
if(!vis[j] && tmp>dis[j]){
k=j;
tmp=dis[j];
}
vis[k]=1;
for(j=1;j<=n;j++)
if(!vis[j] && dis[j]>map[k][j]){
dis[j]=map[k][j];
path[j]=k;
}
}
double d=0,c=0;
for(i=1;i<=n;i++){
d+=dist[i][path[i]];
c+=cost[i][path[i]];
}
return c/d;
}
int main(){
//freopen("input.txt","r",stdin);
while(~scanf("%d",&n) && n){
for(int i=1;i<=n;i++)
scanf("%lf%lf%lf",&e[i].x,&e[i].y,&e[i].z);
for(int i=1;i<=n;i++){
dist[i][i]=cost[i][i]=0;
for(int j=i+1;j<=n;j++){
dist[i][j]=dist[j][i]=sqrt((e[i].x-e[j].x)*(e[i].x-e[j].x)+(e[i].y-e[j].y)*(e[i].y-e[j].y));
cost[i][j]=cost[j][i]=fabs(e[i].z-e[j].z);
}
}
double r1=0,r2=0;
while(1){
r2=Prim(r1);
if(fabs(r1-r2)<=eps)
break;
r1=r2;
}
printf("%.3f\n",r1);
}
return 0;
}