最优比率生成树问题。
是完全图要用prim。顺便学了一发dinkelbach。二分1700ms+ 迭代200ms+很优秀
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int n; double X[1100],Y[1100],Z[1100]; double cst[1100][1100],dis[1100][1100]; double a[1100][1100],d[1100]; bool v[1100]; bool check(double mid) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j) a[i][j]=cst[i][j]-mid*dis[i][j]; memset(v,false,sizeof(v)); memset(d,0x7f,sizeof(d)); for(int i=1;i<n;i++) { int x=-1; for(int j=1;j<=n;j++) if(v[j]==false&&(x==-1||d[x]>d[j]))x=j; v[x]=true; for(int y=1;y<=n;y++) if(v[y]==false)d[y]=min(d[y],a[x][y]); } double ans=0; for(int i=2;i<=n;i++)ans+=d[i]; return (ans<0)||(fabs(ans)<1e-8); } int main() { while(scanf("%d",&n)!=EOF) { if(n==0)break; for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&X[i],&Y[i],&Z[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j) { cst[i][j]=fabs(Z[i]-Z[j]); dis[i][j]=sqrt( (X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j]) ); } double l=0.0,r=100000.0; while(r-l>1e-5) { double mid=(l+r)/2; if(check(mid))r=mid; else l=mid; } printf("%.3lf ",r); } return 0; }
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int n; double X[1100],Y[1100],Z[1100]; double cst[1100][1100],dis[1100][1100]; double a[1100][1100],d[1100]; int p[1100]; bool v[1100]; double check(double mid) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j) a[i][j]=cst[i][j]-mid*dis[i][j]; memset(v,false,sizeof(v)); memset(d,0x7f,sizeof(d)); for(int i=1;i<n;i++) { int x=-1; for(int j=1;j<=n;j++) if(v[j]==false&&(x==-1||d[x]>d[j]))x=j; v[x]=true; for(int y=1;y<=n;y++) if(v[y]==false) { if(d[y]>a[x][y]) { d[y]=a[x][y]; p[y]=x; } } } double sumc=0,sumd=0; for(int i=1;i<=n;i++)sumc+=cst[p[i]][i],sumd+=dis[p[i]][i]; return sumc/sumd; } int main() { while(scanf("%d",&n)!=EOF) { if(n==0)break; for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&X[i],&Y[i],&Z[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j) { cst[i][j]=fabs(Z[i]-Z[j]); dis[i][j]=sqrt( (X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j]) ); } double A=0; while(1) { double B=check(A); if(fabs(A-B)<1e-8)break; else A=B; } printf("%.3lf ",A); } return 0; }