POJ 2728 Desert King (最优比率生成树+分数规划)

题意:
在这里插入图片描述
题解:最优比率生成树+分数规划
重新定义每条边权值为cost - mid * len,mid为总比例,跑mst,直到权值和为0,则为答案。mid即总比例用二分。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
const int maxn = 1e3 + 5;
const double eps = 1e-6;
int n, mst[maxn], m;
double edge[maxn][maxn], lowcost[maxn], co[maxn][maxn];
double prim(double mid) {
    
    
    int i, j, minid;
    double sum = 0, min;
    for (i = 1; i <= n; i++) {
    
    
        lowcost[i] = co[1][i] - mid * edge[1][i];
        mst[i] = 1;
    }
    mst[1] = 0;
    for (i = 2; i <= n; i++) {
    
    
        min = 0x3f3f3f3f;
        minid = 0;
        for (j = 1; j <= n; j++) {
    
    
            if (lowcost[j] < min && mst[j] != 0) {
    
    
                min = lowcost[j];
                minid = j;
            }
        }
        sum += lowcost[minid];
        mst[minid] = 0;
        for (j = 1; j <= n; j++) {
    
    
            if (co[minid][j] - mid * edge[minid][j] < lowcost[j] && mst[j] != 0) {
    
    
                lowcost[j] = co[minid][j] - mid * edge[minid][j];
            }
        }
    }
    return sum;
}
int x[maxn], y[maxn], z[maxn];
double dis(int xa, int ya, int xb, int yb) {
    
    
    return sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb));
}
int 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; i <= n; i++) {
    
    
            for (int j = i + 1; j <= n; j++) {
    
    
                edge[i][j] = edge[j][i] = dis(x[i], y[i], x[j], y[j]);
                co[i][j] = co[j][i] = fabs(z[i] - z[j]);
            }
        }
        double l = 0, r = 40;
        while (r - l > eps) {
    
    
            double mid = (l + r) / 2;
            if (prim(mid) >= 0) l = mid;
            else r = mid;
        }
        printf("%.3f\n", l);
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43680965/article/details/107871885
今日推荐