PKU2728

PKU2728
pku2728
最简单的最优比例生成树。黑书上有类似的题目,只是推出的0-1分数规划的式子不同,思想一样:
MST + bisearch
目前问题是不知如何估计二分搜索的上下界,看discuss上都是卡上下界过的。
 1  #include  < iostream >
 2  #include  < math.h >
 3  #define max(a,b) (a > b ? a:b)
 4  #define min(a,b) (a < b ? a:b)
 5  #define inf  1.5 * 100000000
 6 
 7  using namespace std;
 8 
 9  const   int  maxn = 1001 ;
10  // int place[]
11  double  G[maxn][maxn];
12  double  dis[maxn][maxn];
13  double  h[maxn];
14  int  n;
15 
16  double  prim()
17  {
18        int  i,j,k;
19       bool s[maxn];
20        double  close[maxn];
21       memset(s, false ,sizeof(s));
22        for (i = 0 ;i < n;i ++ ) close[i] = inf;
23       s[ 0 ] = 1 ;
24        for (i = 1 ;i < n;i ++ ) close[i] = G[ 0 ][i];
25        double  total = 0 ;
26        for (i = 1 ;i < n;i ++ ){
27            int  idx;
28            double  mn = inf;
29            for (j = 1 ;j < n;j ++ if ( ! s[j]  &&  close[j] < mn){
30               idx = j;
31               mn = close[j];
32           }
33           s[idx] = 1 ;
34           total += close[idx];
35            for (j = 1 ;j < n;j ++ if ( ! s[j]  &&  close[j] > G[idx][j]) close[j] = G[idx][j];
36       }
37        return  total;
38  }
39  //  给定当前比例r,建新图 
40  void  buildG( double  r)
41  {
42        int  i,j,k;
43        for (i = 0 ;i < n;i ++ for (j = 0 ;j < n;j ++ ) G[i][j] = 0 ;
44        // printf("G with r=%.3lf\n",r);
45        for (i = 0 ;i < n;i ++ ){
46            for (j = i + 1 ;j < n;j ++ ){
47               G[i][j] = G[j][i] = fabs(h[i] - h[j]) - r * dis[i][j];
48                // printf("%.2lf ",G[i][j]);
49           }
50            // printf("\n");
51       }
52  //    printf("\n");
53  }
54 
55  void  read()
56  {
57        int  i,j;
58        double  x[maxn],y[maxn];
59        // scanf("%d",&n);
60        for (i = 0 ;i < n;i ++ ){
61          scanf( " %lf%lf%lf " , & x[i], & y[i], & h[i]);
62       }
63        for (i = 0 ;i < n;i ++ ) dis[i][i] = 0 ;
64        for (i = 0 ;i < n;i ++ for (j = i + 1 ;j < n;j ++ ){
65           dis[i][j] = dis[j][i] = sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
66            // printf("%d %d %.2lf\n",i,j,dis[i][j]);
67       }
68  }
69 
70  void  solve()
71  {
72        //  discuss 里的上下界 
73        double  l = 0 ,h = 31 ,mid = (h + l) / 2 ;
74       buildG(mid);
75        // printf("%.3lf\n",prim());
76       
77        //  二分搜索r_star使得用r_star建立的图的最小生成树权为0 
78       
79        while ( true ){
80            double  res = prim();
81            if (fabs(res) < 1e - 5 break ;
82            if (res < 0 ) h = mid;
83            else  l = mid;
84           mid = (h + l) / 2
85           buildG(mid);
86       }
87       
88       printf( " %.3lf\n " ,mid);
89  }
90 
91  int  main()
92  {
93       while (scanf( " %d " , & n)  &&  n != 0 ){
94          read();
95          solve();
96      }
97  }
98 

你可能感兴趣的:(PKU2728)