沙漠之王【最优比例生成树】【poj2728】

题目传送门

#include<iostream>
#include<algorithm>
#include<cmath>
#include<string.h>
#include<stdio.h>
const int N=3010;
const int inf=0x3f3f3f3f;
using namespace std;
int n;
double x[N],y[N],z[N],d[N][N],g[N][N],ans,xs;
double dis[N];
bool st[N];
double prim(double mid)
{
    memset(st,0,sizeof st);
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    for(int i=2;i<=n;i++)
        dis[i]=d[1][i] - mid*g[1][i];
    for(int i=1;i<n;i++){
        int t=0;
        for(int j=1;j<=n;j++){
            if(!st[j]&&(t==0||dis[t]>dis[j])) t=j;
        }
        st[t]=1;           // t 是距离集合最小的点
        for(int j=1;j<=n;j++)
            if(!st[j]) dis[j]=min(dis[j],d[t][j]-g[t][j]*mid);       // t ----》j 来松弛
      }
    ans=0;
    for(int i=2;i<=n;i++) ans+=dis[i];  //从2到n 个点的dis
    if(ans>=0) return true;
    else return false;
}

double fun(int i,int j)
{
    return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
int main()
{
    int i,j;
    double t;
    while(cin>>n && n)
    {
        for(i=1;i<=n;i++)
        {
            cin>>x[i]>>y[i]>>z[i];
            for(j=1;j<i;j++)
            {
                t=fun(i,j);
                g[i][j]=g[j][i]=t;
                d[i][j]=d[j][i]=abs(z[i]-z[j]);
            }
        }
        double l=0.0,r=1000.0,mid;
        while(r-l>1e-6)
        {
            mid=(l+r)/2;
            if(prim(mid))
                l=mid;
            else
                r=mid;
        }
        printf("%.3f\n",mid);
    }
}

发布了152 篇原创文章 · 获赞 4 · 访问量 3891

猜你喜欢

转载自blog.csdn.net/qq_43716912/article/details/100133022