POJ2728 Desert King

01分数规划

题目传送门

题目大意: n n 个点,两点之间都有道路,道路有两个权值: len= l e n = 两点之间距离, cost= c o s t = 两点高度之差。求使 costlen ∑ c o s t ∑ l e n 最小的生成树的该比值。

这题就是求最优比例生成树。二分比值 mid m i d ,把每条边的权值改为 cost[i]midlen[i] c o s t [ i ] − m i d ∗ l e n [ i ] ,跑最小生成树和0比较即可。

代码(用G++交):

#include
#include
#include
#include
#define N 1005
#define eps 1e-8
#define sqr(x) ((x)*(x))
#define abs(x) ((x)>0?(x):-(x))
using namespace std;
typedef double DB;
struct edge{DB d,c;} ed[N][N];
int n,x[N],y[N],z[N];
bool f[N]; DB d[N];
inline bool pd(DB x){
    memset(f,false,sizeof(f));
    f[1]=true; DB ret=0;
    for (int i=1;i<=n;i++)
        d[i]=ed[1][i].c-x*ed[1][i].d;
    for (int i=1;i<=n-1;i++){
        DB mn=1e50; int now;
        for (int j=1;j<=n;j++)
            if (!f[j]&&d[j]true;
        for (int j=1;j<=n;j++)
            if (!f[j]&&ed[now][j].c-x*ed[now][j].dreturn retint main(){
    while (~scanf("%d",&n)&&n){
        for (int i=1;i<=n;i++)
            scanf("%d%d%d",&x[i],&y[i],&z[i]);
        for (int i=1;ifor (int j=i+1;j<=n;j++){
                DB d=sqrt(1.0*sqr(x[i]-x[j])+1.0*sqr(y[i]-y[j]));
                DB c=abs(z[i]-z[j]);
                ed[i][j]=ed[j][i]=(edge){d,c};
            }
        DB l=0,r=1e10,mid;
        while (r-l>eps)
            if (pd(mid=(l+r)/2)) r=mid-1e-6;
            else l=mid+1e-6;
        printf("%.3f\n",l);
    }
    return 0;
}

你可能感兴趣的:(POJ,其他---分数规划,蒟蒻zxl的Blog专栏)