题目大意:给出
n
个三元组
这是一道经典的分数规划题目。话说为什么我今天才知道有一种算法叫分数规划?逃
考虑二分答案,用
W−mid×dis
建边(其中
W
表示权值,
p.s.话说POJ有毒的吧?为什么我打了两年的%lf从来没炸过?今天就一直爆炸?读入用%lf、输出用%f什么的真的有毒……
附上AC代码:
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int N=1010;
int n,x[N],y[N],w[N];
double map[N][N],l,r,mid,dis[N];
bool b[N];
inline double calc(int i,int j){return fabs(w[i]-w[j])-mid*map[i][j];}
inline bool check(double mid){
double ans=0;
for (int i=2; i<=n; ++i) dis[i]=calc(1,i),b[i]=0;
b[1]=1;
for (int i=1; i<n; ++i){
double mn=1e100;int k=0;
for (int j=1; j<=n; ++j) if (!b[j]&&dis[j]<mn) mn=dis[k=j];
ans+=mn,b[k]=1;
for (int j=1; j<=n; ++j) if (!b[j]&&calc(k,j)<dis[j]) dis[j]=calc(k,j);
}
return ans<1e-10;
}
int main(void){
for (scanf("%d",&n);n;scanf("%d",&n)){
for (int i=1; i<=n; ++i) scanf("%d%d%d",&x[i],&y[i],&w[i]);
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j)
map[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
l=0,r=1e7;
while (r-l>=1e-10)
if (check(mid=(l+r)/2)) r=mid-1e-5;
else l=mid+1e-5;
printf("%.3f\n",l);
}
return 0;
}