• poj-2728Desert King(最优比率生成树)


      题目要求的是MIN( ∑CiXi / ∑DiXi ) Xi∈{0,1},这里xi表示生成树对边的选取,xi=1表示选了,为0表示没有选。

    对每个生成树,设其比率r=∑CiXi / ∑DiXi ,可得∑CiXi - ∑DiXi * r=0,可以知道对于所有的生成树,显然有∑CiXi - ∑DiXi * min(r) >= 0,当 ∑CiXi / ∑DiXi = min(r)时,则有∑CiXi - ∑DiXi * min(r) = 0,而我们现在不知道min(r),但是我们知道它满足这个式子(      ∑CiXi - ∑DiXi * min(r) = ∑xi(ci-min(r)*disi)=0,这个式子很明显是一个生成树的边权和,且当r取到MIN(r)时有∑xi(ci-min(r)*disi)=0,从而问题转化为求以ci-rate*disi为边的权的最小生成树,为什么要求最小生成树?因为当rate取得MIN(r)时有生成树的边权和为0,但是我们不知道生成树边权和为0这种情况存不存在,那么就要每次求都求最小生成树,来寻找使得生成树边权和为0存在的可能性。根据 ∑xi(ci-min(r)*disi)=0这个式子存在,我们可以设一个left=0,right为100,在这个区域用二分法求min(rate),1.当我们枚举的rate使得∑xi(ci-rate*disi)=0时,即求得的最小生成树边权和为0,那么rate=MIN(r)。2.当最小生成树的边权和>0则说明该rate对应的所有生成树的边权和都>0,则∑CiXi - ∑DiXi * rate=0不存在,这种情况是rate取小了。3.当最小生成树的边权和<0则说明该rate对应的所有生成树的边权和都<0,则∑CiXi - ∑DiXi * rate=0不存在,这种情况是rate取大了。

    #include<iostream>
    #include<math.h>
    #include<string.h>
    #include<stdlib.h>
    #include<iomanip>
    using namespace std;
    #define maxn 1005
    #define inf 0x3f3f3f3f
    const double eps=1e-4;
    double cost[maxn][maxn],len[maxn][maxn],x[maxn],y[maxn],z[maxn];
    double mst,w[maxn][maxn],dis[maxn];
    int vis[maxn];
    int n;
    double getdis(double x1,double y1,double x2,double y2)
    {
        return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    
    }
    
    bool prim(double r)
    {
        for(int i=1;i<=n;i++)
        {
            vis[i]=0;
            dis[i]=inf;
            w[i][i]=0;
            for(int j=i+1;j<=n;j++)
                w[i][j]=w[j][i]=cost[i][j]-r*len[i][j];
        }
        dis[1]=0;
        mst=0;
        while(1)
        {
            int u=-1;
            double minn=inf;
            for(int i=1;i<=n;i++)
                if(!vis[i]&&(u==-1||minn>dis[i]))
                {
                    u=i;
                    minn=dis[i];
    
                }
            if(u==-1) break;
            mst+=minn;
            vis[u]=1;
            for(int i=1;i<=n;i++)
            {
                if(!vis[i]&&dis[i]>w[u][i])
                {
                    dis[i]=w[u][i];
                }
            }
        }
        if(mst>0) return  true;
        return false;
    
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        while(cin>>n)
        {
            if(n==0) break;
            for(int i=1;i<=n;i++)
            {
                cin>>x[i]>>y[i]>>z[i];
            }
            for(int i=1;i<=n;i++)
            {
                cost[i][i]=len[i][i]=0;
                for(int j=i+1;j<=n;j++)
                {
                    cost[i][j]=cost[j][i]=fabs(z[i]-z[j]);
                    len[i][j]=len[j][i]=getdis(x[i],y[i],x[j],y[j]);
                }
            }
            double left=0,right=100;
            while((right-left)>=eps)
            {
                double mid=(left+right)/2;
                if(prim(mid))
                    left=mid;
                else
                    right=mid;
    
    
            }
            cout<<fixed<<setprecision(3)<<left<<endl;
    
        }
        return 0;
    }
  • 相关阅读:
    构造函数语义学之Default Constructor构建操作
    c++子类继承父类的覆盖问题
    C++中自己理解的一些细节哈
    学习C++所需看的书和顺序
    C++中强制变换之const_cast
    jquery锚点跳转
    关于iPhone X 适配
    input图片上传并显示查看判断图片类型
    jquery操作按钮修改对应input属性
    织梦dedecms会员中心分类管理无法修改、删除分类名
  • 原文地址:https://www.cnblogs.com/eason9906/p/11755020.html
Copyright © 2020-2023  润新知