[POJ2728 Desert King]

[关键字]:最优比率生成树

[题目大意]:对于一个图有n个点,m条边,每条边有一个ci,bi。求其生成树使得∑ci / bi 最小(或最大)。为方便讨论这里统一记录求min ( ci / bi )

//=====================================================================================================

[分析]:黑书上有详细证明,有些数学符号用电脑打也不太好打,实在懒得写了,这个博客上解答的很详细http://hi.baidu.com/zzningxp/blog/item/b2d1b4ec1f8bbc2262d09fc9.html

[代码]:

View Code
 1 //迭代法
2 #include<cstdio>
3 #include<cstdlib>
4 #include<cstring>
5 #include<cmath>
6 #include<iostream>
7 #include<algorithm>
8 using namespace std;
9
10 const double esp=1e-5;
11 const int MAXN=1010;
12 const double INF=1e9;
13
14 struct point
15 {
16 int x,y,z;
17 } points[MAXN];
18
19 int N;
20 bool v[MAXN];
21 double dis[MAXN];
22 int pre[MAXN];
23
24 double cal(int x,int y)
25 {
26 return sqrt(1.*(points[x].x-points[y].x)*(points[x].x-points[y].x)+1.*(points[x].y-points[y].y)*(points[x].y-points[y].y));
27 }
28
29 double prim(double x)
30 {
31 memset(v,0,sizeof(v));
32 for (int i=2;i<=N;i++)
33 {
34 dis[i]=abs(points[1].z-points[i].z)-x*cal(1,i);
35 pre[i]=1;
36 }
37 dis[1]=0;
38 v[1]=1;
39 double cost=0,len=0;
40 for (int i=1;i<N;i++)
41 {
42 double min=INF;
43 int minj;
44 for (int j=2;j<=N;j++)
45 if (!v[j] && min>dis[j])
46 {
47 min=dis[j];
48 minj=j;
49 }
50 v[minj]=1;
51 cost+=abs(points[pre[minj]].z-points[minj].z);
52 len+=cal(pre[minj],minj);
53 for (int j=2;j<=N;j++)
54 {
55 double val=abs(points[j].z-points[minj].z)-x*cal(minj,j);
56 if (!v[j] && dis[j]>val)
57 {
58 dis[j]=val;
59 pre[j]=minj;
60 }
61 }
62 }
63 return cost/len;
64 }
65
66 int main()
67 {
68 while (scanf("%d",&N),N)
69 {
70 for (int i=1;i<=N;i++)
71 scanf("%d%d%d",&points[i].x,&points[i].y,&points[i].z);
72 double a=0,b;
73 while (1)
74 {
75 b=prim(a);
76 if (fabs(b-a)<esp) break;
77 a=b;
78 }
79 printf("%.3f\n",b);
80 }
81 system("pause");
82 return 0;
83 }



你可能感兴趣的:(des)