PKU2728
pku2728
最简单的最优比例生成树。黑书上有类似的题目,只是推出的0-1分数规划的式子不同,思想一样:
MST + bisearch
目前问题是不知如何估计二分搜索的上下界,看discuss上都是卡上下界过的。
最简单的最优比例生成树。黑书上有类似的题目,只是推出的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
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