http://acm.timus.ru/problem.aspx?space=1&num=1447
最优比率生成树(最小生成树+二分)
黑书 p303
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<vector> #include<stack> #include<set> #include<map> #include<queue> #include<deque> #include<algorithm> #include<cmath> #define LL long long //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const double eps=1e-9; const int INF=0x3f3f3f3f; const double FINF=1e12; const int N=1005; const int M=500005; /* int f[N]; struct node { int l,r,t,c; double tmp; }edge[M]; int x[M]; int fx(int x) { if(f[x]!=x) f[x]=fx(f[x]); return f[x]; } bool cmp(node x,node y) { return x.tmp<y.tmp; } double kruskal(int n,int m,double k) { for(int i=1;i<=n;++i) f[i]=i; for(int i=0;i<m;++i) edge[i].tmp=edge[i].c-k*edge[i].t; sort(edge,edge+m,cmp); for(int i=0;i<m;++i) { if(fx(edge[i].l)==fx(edge[i].r)) {x[i]=0;} else {x[i]=1;f[fx(edge[i].l)]=fx(edge[i].r);} } double sum=0.0; for(int i=0;i<m;++i) { sum+=(edge[i].c-k*edge[i].t)*x[i]; } return sum; } */ int c[N][N],t[N][N],f[N]; double tmp[N][N],dist[N]; bool had[N]; double prim(int n,double k) { for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(c[i][j]!=-1) tmp[i][j]=c[i][j]-k*t[i][j]; for(int i=1;i<=n;++i) dist[i]=FINF; dist[1]=0.0; memset(had,false,sizeof(had)); for(int w=0;w<n;++w) { int l=-1; for(int i=1;i<=n;++i) if(!had[i]&&(l==-1||dist[i]<dist[l])) l=i; had[l]=true; for(int i=1;i<=n;++i) if(!had[i]&&c[l][i]!=-1&&dist[i]>tmp[l][i]) {dist[i]=tmp[l][i];f[i]=l;} } double sum=0.0; for(int i=2;i<=n;++i) sum+=tmp[f[i]][i]; return sum; } int main() { //freopen("data.in","r",stdin); int n,m; while(scanf("%d %d",&n,&m)!=EOF) { memset(c,-1,sizeof(c)); while(m--) { int i,j,t1,c1; scanf("%d %d %d %d",&i,&j,&t1,&c1); t[i][j]=t[j][i]=t1; c[i][j]=c[j][i]=c1; } double l=0.0,r=1e6; double mid; while(r-l>=eps) { mid=(l+r)/2.0; if(prim(n,mid)<=0.0) r=mid; else l=mid; } printf("%.8lf\n",mid); } return 0; }