zoukankan      html  css  js  c++  java
  • POJ 2728 Desert King:最优比率生成树

    题目链接:http://poj.org/problem?id=2728

    题意:

      给你n个点(x,y,z),让你求一棵生成树,使得 k = ∑ |z[i]-z[j]| / ∑ dis(i,j)最小。

      |z[i]-z[j]|为一条边两端点的高度(z)之差,dis(i,j)为两端点在xy平面投影的欧几里得距离。

     

    题解:

      二分答案R。

      如果当前的R还没有达到最小值ans,即R >= ans,则一定有一种方案使得 ∑ |z[i]-z[j]| / ∑ dis(i,j) <= R。

      化简得:

        ∑ (|z[i]-z[j]| - R*dis(i,j)) <= 0

      所以将|z[i]-z[j]| - R*dis(i,j)作为边权,求最小生成树。

      如果求出的MST <= 0,则rig = mid,否则lef = mid。

      注:此题为一个完全图,无优化Prim单次复杂度O(N^2),Kruskal和Prim+Heap单次复杂度O(N^2*log(N^2))。

        然而Kruskal和Prim+Heap被卡了QAQ……

    AC Code:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #define MAX_N 1005
    #define INF_LF 1e10
    #define EPS 1e-4
    
    using namespace std;
    
    int n;
    bool vis[MAX_N];
    double x[MAX_N];
    double y[MAX_N];
    double z[MAX_N];
    double c[MAX_N];
    double a[MAX_N][MAX_N];
    double ans;
    
    void read()
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf",&x[i],&y[i],&z[i]);
        }
    }
    
    void build(double r)
    {
        memset(a,0x7f,sizeof(a));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                double len=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
                a[i][j]=a[j][i]=min(a[i][j],fabs(z[i]-z[j])-r*len);
            }
        }
    }
    
    double prim()
    {
        memset(c,0x7f,sizeof(c));
        memset(vis,false,sizeof(vis));
        c[1]=0;
        double res=0;
        while(true)
        {
            int now=-1;
            double minn=INF_LF;
            for(int i=1;i<=n;i++)
            {
                if(c[i]<minn && !vis[i])
                {
                    now=i;
                    minn=c[i];
                }
            }
            if(now==-1) break;
            vis[now]=true;
            res+=c[now];
            for(int i=1;i<=n;i++)
            {
                c[i]=min(c[i],a[now][i]);
            }
        }
        return res;
    }
    
    bool check(double r)
    {
        build(r);
        return prim()<=0;
    }
    
    void solve()
    {
        double lef=0,rig=100;
        while(rig-lef>EPS)
        {
            double mid=(lef+rig)/2.0;
            if(check(mid)) rig=mid;
            else lef=mid;
        }
        ans=lef;
    }
    
    void print()
    {
        printf("%.3f
    ",ans);
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            if(n==0) break;
            read();
            solve();
            print();
        }
    }
  • 相关阅读:
    你的系统需要做系统集成测试么?
    测试驱动 ASP.NET MVC 和构建可测试 ASP.NET MVC 应用程序
    RikMigrations 或 Migrator.NET 进行自动化的数据库升级
    单元测试
    C#反射
    J2EE--Struts2基础开发
    Dynamics CRM 客户端的插件调试
    于快速创建 IEqualityComparer<T> 实例的类 Equality<T>
    ToolBox Analysis & Design
    实现$.fn.extend 和$.extend函数
  • 原文地址:https://www.cnblogs.com/Leohh/p/8084537.html
Copyright © 2011-2022 走看看