Назад к лучшим решениям Status: AC, problem ZELC, contest ZEL07. By revenger (Denis Nazarov), 2007-02-23 09:40:54.
  1. #include <assert.h>
  2. #include <vector>
  3. #include <string>
  4. #include <algorithm>
  5. #include <iostream>
  6. #include <sstream>
  7. #include <cmath>
  8. #include <set>
  9.  
  10. #define maxn 3000
  11. #define maxm 7000
  12. #define DIST(u, v) ((x[u] - x[v]) * (x[u] - x[v]) + (y[u] - y[v]) * (y[u] - y[v]))
  13. #define POLAR(u, v) atan2(x[v] - x[u], y[v] - y[u])
  14. #define UPDATE(a, b, c, d) \
  15. adj[d].clear(); \
  16. adj[a].erase(b); adj[a].erase(c); adj[b].erase(a); adj[c].erase(a); \
  17. adj[a].insert(d); adj[b].insert(d); adj[c].insert(d); \
  18. adj[d].insert(a); adj[d].insert(b); adj[d].insert(c); \
  19. //cout << a << " " << b << " " << c << " " << d << endl;
  20.  
  21. #define cos60 0.5
  22. #define sin60 0.8660254037844386
  23. #define pi 3.1415926535897932384
  24. #define eps 1e-5
  25. #define eps2 1e-6
  26.  
  27. using namespace std;
  28.  
  29. double x[maxm], y[maxm], best[maxn];
  30. int p[maxn], parent[maxn], n, m;
  31. set<int> adj[maxm];
  32.  
  33. struct adjVertex {
  34. int v;
  35. double phi;
  36.  
  37. adjVertex(int u0, int v) {
  38. this->v = v;
  39. this->phi = POLAR(u0, v);
  40. }
  41. };
  42.  
  43. bool operator<(const adjVertex& a, const adjVertex& b) {
  44. return a.phi > b.phi;
  45. }
  46.  
  47. bool steiner(int a, int b, int c, int d) {
  48. if (b == c || a == b || a == c || d >= 2 * n) return false;
  49.  
  50. double la = DIST(b, c);
  51. double lb = DIST(a, c);
  52. double lc = DIST(a, b);
  53.  
  54. if (la < eps2 || lb < eps2 || lc < eps2) return false;
  55.  
  56. double cosa = (lb + lc - la) / 2.0 / sqrt(lb) / sqrt(lc);
  57. double cosb = (la + lc - lb) / 2.0 / sqrt(la) / sqrt(lc);
  58. double cosc = (la + lb - lc) / 2.0 / sqrt(la) / sqrt(lb);
  59. if (cosa < eps - 0.5 || cosb < eps - 0.5 || cosc < eps - 0.5) return false;
  60.  
  61. if (cosb < cosc && cosb < cosa) return steiner(b, a, c, d);
  62. if (cosc < cosb && cosc < cosa) return steiner(c, a, b, d);
  63.  
  64. double dx = x[b] - x[c];
  65. double dy = y[b] - y[c];
  66. x[d + 1] = dx * cos60 + dy * sin60 + x[c];
  67. y[d + 1] = -dx * sin60 + dy * cos60 + y[c];
  68. x[d + 2] = dx * cos60 - dy * sin60 + x[c];
  69. y[d + 2] = dx * sin60 + dy * cos60 + y[c];
  70.  
  71. int D = DIST(d + 1, a) > DIST(d + 2, a) ? d + 1 : d + 2;
  72. double ld = DIST(a, D);
  73. double cose = (lb + ld - la) / 2.0 / sqrt(lb) / sqrt(ld);
  74. double sine = sqrt(1 - cose * cose);
  75. double phie = acos(cose);
  76. double phif = pi / 3.0 - phie;
  77. double lle = sqrt(lb) * sine / sin60;
  78. double cosf = cos(phif);
  79. double sinf = sin(phif);
  80.  
  81. dx = (x[a] - x[c]) / sqrt(lb) * lle;
  82. dy = (y[a] - y[c]) / sqrt(lb) * lle;
  83. x[d + 1] = dx * cosf + dy * sinf + x[c];
  84. y[d + 1] = -dx * sinf + dy * cosf + y[c];
  85. x[d + 2] = dx * cosf - dy * sinf + x[c];
  86. y[d + 2] = dx * sinf + dy * cosf + y[c];
  87.  
  88. D = DIST(d + 1, b) < DIST(d + 2, b) ? d + 1 : d + 2;
  89. x[d] = x[D];
  90. y[d] = y[D];
  91.  
  92. return (x[d] > -1e6 && x[d] < 1e6 && y[d] > -1e6 && y[d] < 1e6);
  93. }
  94.  
  95. void greedy() {
  96. int i, j, current, first, k;
  97. m = 0;
  98.  
  99. for (i = 0; i < n; i++) if (adj[i].size() > 1) {
  100. vector<adjVertex> adjv;
  101. for (set<int>::iterator it = adj[i].begin(); it != adj[i].end(); it++) adjv.push_back(adjVertex(i, *it));
  102. sort(adjv.begin(), adjv.end());
  103.  
  104. current = adjv[0].v;
  105. first = current;
  106.  
  107. bool failed = false;
  108. for (j = 1; j < adjv.size(); j++)
  109. if (steiner(i, current, adjv[j].v, n + m)) {
  110. UPDATE(i, current, adjv[j].v, n + m)
  111. current = n + m;
  112. if (!failed) first = current;
  113. m += 1;
  114. } else {
  115. current = adjv[j].v;
  116. failed = true;
  117. }
  118.  
  119. if (steiner(i, first, current, n + m)) {
  120. UPDATE(i, first, current, n + m)
  121. m += 1;
  122. }
  123. }
  124. }
  125.  
  126. int main() {
  127. /*freopen("zelc.in", "rt", stdin);
  128. freopen("zelc.out", "wt", stdout);*/
  129.  
  130. srand(30051985);
  131.  
  132. int testCount, i, j, k, lim, v0;
  133. scanf("%d", &testCount);
  134. while (testCount--) {
  135. scanf("%d", &n);
  136. v0 = 1;
  137. for (i = 0; i < n; i++) scanf("%lf %lf", &x[i], &y[i]);
  138. for (i = 0; i < n; i++) {
  139. best[i] = DIST(v0, i);
  140. p[i] = i < v0 ? i : i + 1;
  141. parent[i] = v0;
  142. }
  143. for (lim = n - 1, i = 1; i < n; i++) {
  144. for (k = 0, j = 0; j < lim; j++) if (best[p[k]] > best[p[j]]) k = j;
  145. m = p[k];
  146. p[k] = p[--lim];
  147. for (j = 0; j < lim; j++) {
  148. double dist = DIST(m, p[j]);
  149. if (best[p[j]] > dist) {
  150. best[p[j]] = dist;
  151. parent[p[j]] = m;
  152. }
  153. }
  154. }
  155.  
  156. for (i = 0; i < n; i++) adj[i].clear();
  157. for (i = 0; i < n; i++) if (i != v0) {
  158. adj[i].insert(parent[i]);
  159. adj[parent[i]].insert(i);
  160. }
  161.  
  162. greedy();
  163.  
  164. printf("%d\n", m);
  165. for (i = n; i < n + m; i++) printf("%lf %lf\n", x[i], y[i]);
  166. printf("%d\n", n + m - 1);
  167. for (j = 0, i = 0; i < n + m; i++) {
  168. for (set<int>::iterator it = adj[i].begin(); it != adj[i].end(); it++) {
  169. int vertex = *it;
  170. if (vertex > i) { printf("%d %d\n", i, vertex); j++; };
  171. }
  172. }
  173. }
  174. }