最优比率生成树
题意:给出点的坐标和高度,任意两点之间存在两个权值,一个是高度差的绝对值ci,一个是两点之间的距离leni,求权值$\sum_{i=1}^n\frac{c_{i}}{len_{i}}$最小的生成树。0/1分数规划问题:在可取可不取的情况下,求最大或者最小\(\sum_{i=1}^n\frac{a_{i}}{b_{i}}\)。
二分枚举L
求最大:\(\sum_{i=1}^n(a_{i}-L\times b_{i})\)的最大值小于0,则L不是可行解,否则L是可行解。
求最小:\(\sum_{i=1}^n(a_{i}-L\times b_{i})\)的最小值大于等于0,则L不是可行解,否则L是可行解。
思路:把图的权值改成c - ans\(\times\)len,求最小生成树,二分求最小可行解ans。
注意:稠密图kruskal会超时
#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <map>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
const int MaxnN = 1000+10;
const int MaxnM = 1e6+10;
const int INF = 0x3f3f3f3f;
const ll LINF = 1e18;
const double eps = 1e-6;
int n;
double mincost[MaxnN], c[MaxnN][MaxnN], len[MaxnN][MaxnN];
pair<int, pair<int, int> > p[MaxnN];
bool vis[MaxnN];
double dis(pair<int, int> x, pair<int, int> y) {
return sqrt((double)(x.first-y.first)*(x.first-y.first)
+(double)(x.second-y.second)*(x.second-y.second));
}
bool ok(double mid) {
double res = 0;
for(int i = 1; i <= n; ++i) {
mincost[i] = LINF;
vis[i] = false;
}
mincost[1] = 0;
while(1) {
int u = -1;
for(int i = 1; i <= n; ++i) if(!vis[i] && (u == -1 || mincost[u] > mincost[i])) u = i;
if(u == -1) break;
vis[u] = true;
res += mincost[u];
for(int v = 1; v <= n; ++v) {
if(!vis[v] && mincost[v] > c[u][v]-mid*len[u][v]) {
mincost[v] = c[u][v]-mid*len[u][v];
}
}
}
if(res >= eps) return false;
else return true;
}
int main(void)
{
while(scanf("%d", &n) != EOF) {
if(!n) break;
for(int i = 1; i <= n; ++i) {
scanf("%d%d%d", &p[i].first, &p[i].second.first, &p[i].second.second);
}
double t1, t2;
for(int i = 1; i <= n; ++i) {
for(int j = i+1; j <= n; ++j) {
t1 = abs(p[i].second.second-p[j].second.second);
t2 = dis(make_pair(p[i].first, p[i].second.first), make_pair(p[j].first, p[j].second.first));
c[i][j] = c[j][i] = t1;
len[i][j] = len[j][i] = t2;
}
}
double L = 0, R = 1000.0, mid;
while(L < R-eps) {
mid = (L+R)/2;
if(ok(mid)) R = mid;
else L = mid+eps;
}
printf("%.3f\n", R);
}
return 0;
}
浙公网安备 33010602011771号