Poj 2728 Desert King
http://poj.org/problem?id=2728
题意:一个无向图,每条边有两个边权,cost和len,求出一个最小生成树,使所有边的cost/len和最小。
题解:最优比率生成树:http://www.cnblogs.com/lotus3x/archive/2009/03/21/1418480.html
使用迭代法,代码抄的http://www.cnblogs.com/crazyapple/p/3264223.html ……
作为板子好了……应该不会经常见到这种题。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cmath> 6 #include <string> 7 #include <vector> 8 #include <list> 9 #include <map> 10 #include <queue> 11 #include <stack> 12 #include <bitset> 13 #include <algorithm> 14 #include <numeric> 15 #include <functional> 16 #include <set> 17 #include <fstream> 18 19 //using namespace std; 20 21 const int INF=0xfffffff; 22 const double exps=1e-8; 23 const int maxn=1010; 24 25 double dis[maxn]; 26 int pre[maxn],used[maxn]; 27 int N; 28 29 struct node{ 30 int x,y,z; 31 }p[maxn]; 32 33 double distance(node a,node b) 34 { 35 return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y)); 36 } 37 38 double prim(double r) 39 { 40 memset(used,0,sizeof(used)); 41 for(int i=2;i<=N;i++) 42 { 43 dis[i]=abs(p[1].z-p[i].z)-distance(p[1],p[i])*r; 44 pre[i]=1; 45 } 46 dis[1]=0; 47 used[1]=1; 48 double cost=0,len=0; 49 for(int i=1;i<N;i++) 50 { 51 double mins=INF; 52 int k=-1; 53 for(int j=2;j<=N;j++) 54 { 55 if(!used[j]&&mins>dis[j]) 56 { 57 mins=dis[j]; 58 k=j; 59 } 60 } 61 if(k==-1) break; 62 used[k]=1; 63 cost+=abs(p[pre[k]].z-p[k].z); 64 len+=distance(p[pre[k]],p[k]); 65 for(int j=2;j<=N;j++) 66 { 67 double val=abs(p[k].z-p[j].z)-distance(p[k],p[j])*r; 68 if(!used[j]&&dis[j]>val) 69 { 70 dis[j]=val; 71 pre[j]=k; 72 } 73 } 74 } 75 return cost/len; 76 } 77 78 int main() 79 { 80 //freopen("/Users/apple/Desktop/暑假/20/20/in","r",stdin); 81 while(scanf("%d",&N)!=EOF&&N) 82 { 83 for(int i=1;i<=N;i++) 84 { 85 scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z); 86 } 87 double ri=0,res=0; 88 while(1) 89 { 90 res=prim(ri); 91 if(abs(ri-res)<exps) break; 92 ri=res; 93 } 94 printf("%.3lf\n",res); 95 } 96 return 0; 97 }