藍書(演算法競賽進階指南)刷題記錄——POJ2728 Desert King(最優比例生成樹)
阿新 • • 發佈:2018-11-10
題目: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.