UVALive - 5713 最小生成树

题意:

秦始皇修路,已知n个城市的坐标以及该城市的人口数,修路的费用是两个城市之间的欧几里得距离,其中可以有一条路不用花费代价但是要求这条路连接的两个城市的人口之和A/B尽量大,其中B是修路的总费用。

输入t组数据

输入n城市个数

输入n行x,y,z表示坐标和人口数

 

输出A/B.

代码:

//类似次小生成树的处理方法,先求出最小生成树值ans,枚举要选的边u-v,ans减去u-v路径中的最大权值之后比较比值大小。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const double inf=10000007.0;
int t,n,vis[1010],pre[1010];
double maxl[1010][1010],dis[1010],x[1010],y[1010],w[1010],mp[1010][1010];
double Prim(){
    memset(maxl,0,sizeof(maxl));
    for(int i=0;i<n;i++){
        dis[i]=mp[0][i];
        vis[i]=0;pre[i]=0;
    }
    vis[0]=1;
    double ans=0;
    for(int i=1;i<n;i++){
        double minl=inf;int sta=-1;
        for(int j=0;j<n;j++){
            if(!vis[j]&&dis[j]<minl){
                minl=dis[j];
                sta=j;
            }
        }
        if(sta==-1) return -1;
        vis[sta]=1;
        ans+=minl;
        for(int j=0;j<n;j++){
            if(vis[j]&&j!=sta) 
                maxl[sta][j]=maxl[j][sta]=max(maxl[pre[sta]][j],dis[sta]);
            else if(!vis[j]&&dis[j]>mp[sta][j]){
                dis[j]=mp[sta][j];
                pre[j]=sta;
            }
        }
    }
    return ans;
}
double Smst(double ans){
    double tmp=0;
    for(int i=0;i<n-1;i++){
        for(int j=i+1;j<n;j++){
            tmp=max(tmp,(w[i]+w[j])/(ans-maxl[i][j]));
        }
    }
    return tmp;
}
int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%lf%lf%lf",&x[i],&y[i],&w[i]);
            mp[i][i]=0;
            for(int j=0;j<i;j++)
                mp[i][j]=mp[j][i]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
        }
        double ans=Prim();
        ans=Smst(ans);
        printf("%.2lf\n",ans);
    }
    return 0;
}

 

posted @ 2017-04-23 17:40  luckilzy  阅读(305)  评论(0编辑  收藏  举报