最小割
最优比率生成树
poj 2728 Desert King http://poj.org/problem?id=2728
题意:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,
建造水管距离为坐标之间的欧几里德距离(好象是叫欧几里德距离吧),费用为海拔之差
现在要求方案使得费用与距离的比值最小
http://www.cppblog.com/jh818012/articles/167743.html
1 #include<iostream> 2 #include<string.h> 3 #include<stdio.h> 4 #include<math.h> 5 using namespace std; 6 #define INF 10000000 7 int x[1002],y[1002],h[1002],n; 8 double dis[1002][1002],high[1002][1002],d[1002],vis[1002]; 9 10 double prim(double r) 11 { 12 int i,j; 13 for(i=2;i<=n;i++) 14 d[i]=high[1][i]-dis[1][i]*r; 15 memset(vis,0,sizeof(vis)); 16 vis[1]=1; 17 double p=0; 18 for(i=1;i<n;i++) 19 { 20 double minn=INF; 21 int v; 22 for(j=1;j<=n;j++) 23 if(!vis[j]&&minn>d[j]) 24 { 25 minn=d[j]; 26 v=j; 27 } 28 p+=minn; 29 vis[v]=1; 30 31 for(j=1;j<=n;j++) 32 if(!vis[j]) 33 if(d[j]>high[v][j]-dis[v][j]*r) 34 d[j]=high[v][j]-dis[v][j]*r; 35 36 } 37 return p; 38 } 39 40 int main() 41 { 42 int i,j,m,t; 43 while(scanf("%d",&n)) 44 { 45 46 if(n==0) 47 break; 48 double max=0.0; 49 for(i=1;i<=n;i++) 50 scanf("%d%d%d",&x[i],&y[i],&h[i]); 51 52 for(i=1;i<=n;i++) 53 for(j=i+1;j<=n;j++) 54 { 55 double b; 56 b=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]); 57 dis[i][j]=dis[j][i]=sqrt(b); 58 high[i][j]=high[j][i]=abs(h[i]-h[j]); 59 if(max<high[i][j]/dis[i][j]) 60 max=high[i][j]/dis[i][j]; 61 } 62 //printf("max %lf\n",max); 63 double right=max,left=0.0, ans,mid; 64 while(right>left) 65 { 66 mid=(right+left)/2; 67 ans=prim(mid); 68 if(fabs(ans-0.0)<0.0005) 69 break; 70 else if(ans>=0.0005) 71 left=mid; 72 else right=mid; 73 } 74 printf("%.3lf\n",mid); 75 } 76 return 0; 77 } 78 79