题目链接:http://poj.org/problem?id=2728
题目大意:
在这么一个图中求一棵生成树,这棵树的单位长度的花费最小是多少?

思路:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<math.h>

#define LL long long
using namespace std;

LL x[1005], y[1005], z[1005];
LL mp[1005][1005];
double w[1005][1005];

int check(double mid, int n){

    double dis[1005]={0};
    bool vis[1005]={0};
    double sum=0;
    for(int i=1; i<=n; i++){
        dis[i]=mp[1][i]-mid*w[1][i];//以dis[i]为参照,选取最小的n-1个
    }
    vis[1]=1;
    int N=n-1;
    while(N--){
        double min_f=(1ll<<50);
        int v=-1;
        for(int j=1; j<=n; j++){
            if(vis[j]==0&&dis[j]<min_f){
                min_f=dis[j];
                v=j;
            }
        }
        sum+=min_f;
        vis[v]=1;
        for(int i=1; i<=n; i++){
            if(vis[i]==0&&mp[v][i]-mid*w[v][i]<dis[i]){
                dis[i]=mp[v][i]-mid*w[v][i];
            }
        }
    }
    return sum>=0;
}

int main(){

    int n;
    while(scanf("%d", &n), n){

        for(int i=1; i<=n; i++){
            scanf("%lld%lld%lld", &x[i], &y[i], &z[i]);
        }
        for(int i=1; i<=n; i++){
            for(int j=i+1; j<=n; j++){
                mp[i][j]=abs((int)(z[i]-z[j]));
                mp[j][i]=abs((int)(z[i]-z[j]));
                w[i][j]=w[j][i]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
            }
        }
        double L=0, R=(1ll<<30);
        for(int i=1; i<=50; i++){
            double mid=(L+R)/2;
            if(check(mid, n)){
                L=mid;
            }
            else{
                R=mid;
            }
        }
        printf("%.3f\n", R);
    }

    return 0;
}