版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/83143046
题目:POJ2728.
题目大意:给定一张无向完全图,有边权a和b,求出它的最优比例生成树满足a之和除以b之和最大.
我们发现这也是一个0-1分数规划的模型.
根据0-1分数规划的套路,我们二分一个比例mid,把这张图的所有边的边权换成,然后跑一遍最大生成树,判断边权和是否大于0即可.
代码如下:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=1000;
const double eps=1e-6,INF=1e9;
int n;
double x[N+9],y[N+9],z[N+9];
double a[N+9][N+9],b[N+9][N+9],dis[N+9][N+9],d[N+9];
bool use[N+9];
double l,r,mid;
double distance(double x1,double y1,double x2,double y2){return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}
double check(double mid){
double sum=0;
for (int i=0;i<=n;i++)
use[i]=0,d[i]=INF;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
dis[i][j]=a[i][j]-mid*b[i][j];
d[1]=0;
for (int i=1;i<=n;i++){
int v=0;
for (int j=1;j<=n;j++)
if (!use[j]&&d[v]>d[j]) v=j;
sum+=d[v];use[v]=1;
for (int j=1;j<=n;j++)
if (!use[j]&&d[j]>dis[v][j]) d[j]=dis[v][j];
}
return sum;
}
Abigail into(){
for (int i=1;i<=n;i++)
scanf("%lf%lf%lf",&x[i],&y[i],&z[i]);
}
Abigail work(){
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++){
a[i][j]=fabs(z[i]-z[j]);
b[i][j]=distance(x[i],y[i],x[j],y[j]);
}
l=0;r=1e6;
while (l+eps<r){
mid=(l+r)/2;
if (check(mid)>0) l=mid;
else r=mid;
}
}
Abigail outo(){
printf("%.3f\n",mid);
}
int main(){
while (~scanf("%d",&n)&&n){
into();
work();
outo();
}
return 0;
}
一定要记住G++编译器用%f输出,C++编译器用%lf输出.
然后这道题还会卡常,eps和r之间的差距太大就会TLE.