poj2728

题意:一个无向图,每条边有两个权值,c和l,要求一个生成树,使得所有边的c的和比上l的和最小。

分析:最优比例生成树。现在要求(c1+...)/(l1+...),设一个比例值变量为r。令r>=(c1+...)/(l1+...)。现在题目转化为求r的最小值。

假设我们对于一个确定的r可以判断该不等式是否可以满足,那么我们可以用二分查找的方法来求r的最小值,因为r猜大了则可满足,猜小了则不可满足。

然而,我们确实可以对于一个确定的r来判定是否可满足不等式,方法如下:

现在r是确定的,相当于已知r。先将不等式整理为如下形式:(r*l1-c1)+...>=0,然后我们使不等式左边尽量大即可。现在不等式左边的的每个括号里都只与一个边有关,把这个括号里的值作为这个边的权值,求图的最大生成树即可使得左边最大。

View Code
#include <iostream>
#include
<cstdio>
#include
<cstdlib>
#include
<cstring>
#include
<cmath>
usingnamespace std;

#define maxn 1005
#define eps 0.0001
#define inf 1000000000

struct Village
{
int x, y, z;
} village[maxn];

double dist[maxn][maxn], map[maxn][maxn], mindist[maxn];
int height[maxn][maxn], n;
bool vis[maxn];

double getdist(const Village &a, const Village &b)
{
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

void input()
{
for (int i =0; i < n; i++)
scanf(
"%d%d%d", &village[i].x, &village[i].y, &village[i].z);
for (int i =0; i < n; i++)
for (int j = i +1; j < n; j++)
{
dist[i][j]
= dist[j][i] = getdist(village[i], village[j]);
height[i][j]
= height[j][i] = abs(village[i].z - village[j].z);
}
}

void makemap(double mid)
{
for (int i =0; i < n; i++)
for (int j = i +1; j < n; j++)
map[j][i]
= map[i][j] =- mid * dist[i][j] + height[i][j];
}

double prim(double dist[])
{
double ans =0;
for (int i =0; i < n; i++)
dist[i]
= inf;
memset(vis,
0, sizeof(vis));
dist[
0] =0;
while (1)
{
double mindist = inf;
int mini =-1;
for (int i =0; i < n; i++)
if (dist[i] < mindist &&!vis[i])
{
mindist
= dist[i];
mini
= i;
}
if (mini ==-1)
return ans;
vis[mini]
=true;
ans
+= mindist;
for (int i =0; i < n; i++)
if (!vis[i] && map[mini][i] < dist[i])
dist[i]
= map[mini][i];
}
}

double binarysearch()
{
double l =0, r =1000000000;
while (r - l > eps)
{
double mid = (l + r) /2;
makemap(mid);
double temp = prim(mindist);
if (temp >=0)
l
= mid;
else
r
= mid;
}
return l;
}

int main()
{
//freopen("D:\\t.txt", "r", stdin);
while (scanf("%d", &n) != EOF && n !=0)
{
input();
printf(
"%.3f\n", binarysearch());
}
return0;
}
原文地址:https://www.cnblogs.com/rainydays/p/1993091.html