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 }

 

posted @ 2014-07-28 19:58  Der_Z  阅读(138)  评论(0编辑  收藏  举报