Назад к лучшим решениям Status: AC, problem ZELC, contest ZEL07. By werewolf (Werewolf), 2007-03-10 03:57:25.
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5.  
  6. #define PREC 0.001
  7. #define MAX_NODES 3004
  8. #define MAX_TRIANGLES (2*MAX_NODES+1)
  9. #define MAX_EDGES (2*MAX_TRIANGLES +1)
  10.  
  11. #define CACHE_INCREASE_COEF 12
  12. #define MAX_CACHE_SIZE 64
  13.  
  14. typedef struct _COORD
  15. {
  16. float x;
  17. float y;
  18. } COORD, *PCOORD;
  19.  
  20. typedef struct _NODE
  21. {
  22. COORD crd;
  23. int id;
  24. } NODE, *PNODE;
  25.  
  26.  
  27. typedef struct _TRIANGLE
  28. {
  29. NODE * n1, * n2, * n3;
  30. struct _TRIANGLE * t1, *t2, *t3;
  31. float d1, d2, d3;
  32. char usedEdges;
  33. } TRIANGLE, *PTRIANGLE;
  34.  
  35. typedef struct _REBUILD_ITEM
  36. {
  37. PTRIANGLE toProcess;
  38. PTRIANGLE toExclude;
  39. }REBUILD_ITEM, *PREBUILD_ITEM;
  40.  
  41. typedef struct _EDGE
  42. {
  43. float d;
  44. int n1;
  45. int n2;
  46. PTRIANGLE trg1, trg2;
  47. }EDGE, *PEDGE;
  48.  
  49. typedef struct _TRG_SQUARE
  50. {
  51. float sqr;
  52. PTRIANGLE trg;
  53. }TRG_SQUARE, *PTRG_SQUARE;
  54.  
  55. struct NORMALIZE
  56. {
  57. float minx, maxx, miny, maxy;
  58. float divx;
  59. float divy;
  60. } norm;
  61.  
  62. PTRIANGLE cache[MAX_CACHE_SIZE][MAX_CACHE_SIZE];
  63. int cache_size = 2;
  64.  
  65. REBUILD_ITEM rebuild_queue[MAX_TRIANGLES];
  66. int start_queue = 0, end_queue = 0;
  67.  
  68. #define vect_abs_2(a) ((a).x*(a).x + (a).y*(a).y)
  69. #define segm_abs_2(a,b) (((a).x-(b).x)*((a).x-(b).x) + ((a).y-(b).y)*((a).y-(b).y))
  70. #define dots_equal(a, b) ((a).x==(b).x && (a).y==(b).y)
  71.  
  72. TRIANGLE triangles[MAX_TRIANGLES];
  73. PTRIANGLE pnexttrg = triangles;
  74. int nTriangles = 0;
  75.  
  76. NODE nodes[MAX_NODES+MAX_NODES-2];
  77. int nNodes = 0;
  78. int nSteinerNodes = 0;
  79.  
  80. EDGE edges[MAX_EDGES];
  81. int nEdges = 0;
  82.  
  83.  
  84. typedef void (*MSTCALLBACK)(PEDGE pArc);
  85.  
  86. __inline void addEdge(int node1, int node2, float d, PTRIANGLE trg1, PTRIANGLE trg2)
  87. {
  88. edges[nEdges].trg1 = trg1;
  89. edges[nEdges].trg2 = trg2;
  90. edges[nEdges].d = d;
  91. edges[nEdges].n1 = node1;
  92. edges[nEdges++].n2 = node2;
  93. }
  94. __inline PTRIANGLE addTriangle(PNODE a, PNODE b, PNODE c)
  95. {
  96. pnexttrg->n1 = a;
  97. pnexttrg->n2 = b;
  98. pnexttrg->n3 = c;
  99. pnexttrg->d1 = pnexttrg->d2 = pnexttrg->d3 = 0;
  100. pnexttrg->usedEdges = 0;
  101. nTriangles++;
  102. return pnexttrg++;
  103. }
  104. __inline void pushToRebuild(PTRIANGLE trg, PTRIANGLE excl)
  105. {
  106. int i;
  107. for(i = start_queue; i < end_queue; i++)
  108. if(trg == rebuild_queue[i].toProcess) return;
  109.  
  110. rebuild_queue[end_queue].toProcess = trg;
  111. rebuild_queue[end_queue++].toExclude = excl;
  112. }
  113. void increaseCache()
  114. {
  115. int i, j;
  116. for(i = cache_size-1; i >= 0; i--)
  117. {
  118. for(j = cache_size-1; j >= 0; j--)
  119. {
  120. cache[2*i][2*j] = cache[2*i][2*j+1] =
  121. cache[2*i+1][2*j] = cache[2*i+1][2*j+1] = cache[i][j];
  122. }
  123. }
  124. cache_size*=2;
  125. }
  126. __inline PTRIANGLE popToRebuild(PTRIANGLE * pexcl)
  127. {
  128. PTRIANGLE ret;
  129. if(start_queue == end_queue) return 0;
  130. ret = rebuild_queue[start_queue].toProcess;
  131. *pexcl = rebuild_queue[start_queue++].toExclude;
  132.  
  133. if(start_queue == end_queue) start_queue = end_queue = 0;
  134. return ret;
  135. }
  136. enum {LEFT, RIGHT, BEYOND, BEHIND, BETWEEN, START, END};
  137. int dotRelation(PCOORD dot, PCOORD start, PCOORD end)
  138. {
  139. COORD a = {end->x - start->x, end->y - start->y};
  140. COORD b = {dot->x - start->x, dot->y - start->y};
  141. float sa = a.x * b.y - b.x * a.y;
  142. if(sa > PREC)
  143. return LEFT;
  144. if(sa < -PREC)
  145. return RIGHT;
  146. if((a.x * b.x < 0.0) || (a.y * b.y < 0.0))
  147. return BEHIND;
  148. if(vect_abs_2(a) < vect_abs_2(b))
  149. return BEYOND;
  150. if(dots_equal(*start, *dot))
  151. return START;
  152. if(dots_equal(*end, *dot))
  153. return END;
  154. return BETWEEN;
  155. }
  156.  
  157. __inline int whereIsDot(PCOORD dot, PTRIANGLE trg)
  158. {
  159. if(dotRelation (dot, &trg->n1->crd, &trg->n2->crd) == LEFT)
  160. return 1;
  161. if(dotRelation (dot, &trg->n2->crd, &trg->n3->crd) == LEFT)
  162. return 2;
  163. if(dotRelation (dot, &trg->n3->crd, &trg->n1->crd) == LEFT)
  164. return 3;
  165. return 0;
  166. }
  167. PTRIANGLE findTriangle(PCOORD dot)
  168. {
  169. int a, b;
  170. PTRIANGLE tmp;
  171. a = (int)floor(((dot->x - norm.minx)*cache_size)/norm.divx);
  172. b = (int)floor(((dot->y - norm.miny)*cache_size)/norm.divy);
  173. tmp = cache[a][b];
  174.  
  175. for(;;)
  176. {
  177. switch(whereIsDot(dot, tmp))
  178. {
  179. case 0:
  180. break;
  181. case 1:
  182. tmp = tmp->t1;
  183. continue;
  184. case 2:
  185. tmp = tmp->t2;
  186. continue;
  187. case 3:
  188. tmp = tmp->t3;
  189. continue;
  190. }
  191. break;
  192. }
  193. cache[a][b] = tmp;
  194. return tmp;
  195. }
  196. __inline void rotateNodesFor(PTRIANGLE trg)
  197. {
  198. PNODE tmpn;
  199. PTRIANGLE tmpt;
  200.  
  201. tmpn = trg->n3;
  202. trg->n3 = trg->n2;
  203. trg->n2 = trg->n1;
  204. trg->n1 = tmpn;
  205.  
  206. tmpt = trg->t3;
  207. trg->t3 = trg->t2;
  208. trg->t2 = trg->t1;
  209. trg->t1 = tmpt;
  210. }
  211. __inline void rotateNodesRev(PTRIANGLE trg)
  212. {
  213. PNODE tmpn;
  214. PTRIANGLE tmpt;
  215.  
  216. tmpn = trg->n1;
  217. trg->n1 = trg->n2;
  218. trg->n2 = trg->n3;
  219. trg->n3 = tmpn;
  220.  
  221. tmpt = trg->t1;
  222. trg->t1 = trg->t2;
  223. trg->t2 = trg->t3;
  224. trg->t3 = tmpt;
  225. }
  226. __inline void updateTriangleRef(PTRIANGLE trg, PTRIANGLE ref, PTRIANGLE upd)
  227. {
  228. if( trg->t1 == ref )
  229. trg->t1 = upd;
  230. else if( trg->t2 == ref )
  231. trg->t2 = upd;
  232. else if( trg->t3 == ref )
  233. trg->t3 = upd;
  234. }
  235. int checkDelaunay(PCOORD dot, PTRIANGLE trg)
  236. {
  237. // the 1-2 edge must be between the dot and node3
  238. float sa, sb;
  239. PCOORD c0 = dot, c1 = &trg->n2->crd, c2 = &trg->n3->crd, c3 = &trg->n1->crd;
  240.  
  241. sa = (c1->x - c0->x)*(c3->x - c0->x) + (c1->y - c0->y)*(c3->y - c0->y);
  242. sb = (c1->x - c2->x)*(c3->x - c2->x) + (c1->y - c2->y)*(c3->y - c2->y);
  243. if(sa < 0 && sb < 0) return 0;
  244. if(sa >= 0 && sb >= 0) return 1;
  245.  
  246. return ((((c3->x - c0->x)*(c1->y - c0->y) - (c1->x - c0->x)*(c3->y - c0->y)) * sb +
  247. ((c1->x - c2->x)*(c3->y - c2->y) - (c3->x - c2->x)*(c1->y - c2->y)) * sa) >= 0);
  248. }
  249. void rebuildTriangles()
  250. {
  251. int nCheck;
  252. PTRIANGLE trg1, trg2, excl;
  253. while(trg1 = popToRebuild(&excl))
  254. {
  255. nCheck = 3;
  256. do
  257. {
  258. trg2 = trg1->t1;
  259. if(!trg2 || trg2 == excl) continue;
  260. while(trg2->t1 != trg1) rotateNodesFor(trg2);
  261. if(checkDelaunay(&trg2->n3->crd, trg1)) continue;
  262.  
  263. // rebuild triangles
  264. trg1->n2 = trg2->n3;
  265. trg2->n2 = trg1->n3;
  266.  
  267. if(trg1->t2) updateTriangleRef(trg1->t2, trg1, trg2);
  268. if(trg2->t2) updateTriangleRef(trg2->t2, trg2, trg1);
  269.  
  270. trg1->t1 = trg2->t2;
  271. trg2->t1 = trg1->t2;
  272.  
  273. trg1->t2 = trg2;
  274. trg2->t2 = trg1;
  275.  
  276. pushToRebuild(trg2, trg1);
  277. nCheck = 3;
  278. rotateNodesRev(trg1);
  279. } while(rotateNodesRev(trg1), --nCheck);
  280. }
  281. }
  282. void splitTriangle(PNODE node, PTRIANGLE trg)
  283. {
  284. int r1, r2, r3;
  285. PTRIANGLE trg1 = 0, trg2 = 0;
  286. r1 = dotRelation (&node->crd, &trg->n1->crd, &trg->n2->crd);
  287. r2 = dotRelation (&node->crd, &trg->n2->crd, &trg->n3->crd);
  288. r3 = dotRelation (&node->crd, &trg->n3->crd, &trg->n1->crd);
  289. if(r1 == RIGHT && r2 == RIGHT && r3 == RIGHT)
  290. {
  291. // the dot in the triangle
  292. trg1 = addTriangle(node, trg->n1, trg->n2);
  293. trg2 = addTriangle(node, trg->n3, trg->n1);
  294. trg->n1 = node;
  295.  
  296. if(trg->t1) updateTriangleRef(trg->t1, trg, trg1);
  297. if(trg->t3) updateTriangleRef(trg->t3, trg, trg2);
  298.  
  299. trg1->t1 = trg2;
  300. trg1->t2 = trg->t1;
  301. trg1->t3 = trg;
  302.  
  303. trg2->t1 = trg;
  304. trg2->t2 = trg->t3;
  305. trg2->t3 = trg1;
  306.  
  307. trg->t1 = trg1;
  308. trg->t3 = trg2;
  309. pushToRebuild(trg, trg2);
  310. pushToRebuild(trg1, trg);
  311. pushToRebuild(trg2, trg1);
  312. }else
  313. {
  314. if(r1 == BETWEEN) {}
  315. else if(r2 == BETWEEN)
  316. rotateNodesRev(trg);
  317. else if(r3 == BETWEEN)
  318. rotateNodesFor(trg);
  319. else
  320. return;
  321.  
  322. if(trg->t1)
  323. while(trg->t1->t1 != trg) rotateNodesFor(trg->t1);
  324.  
  325. // the dot on the edge 1-2 now
  326. trg1 = addTriangle(node, trg->n3, trg->n1);
  327. trg->n1 = node;
  328. if(trg->t1)
  329. {
  330. trg2 = addTriangle(node, trg->t1->n3, trg->t1->n1);
  331. trg->t1->n1 = node;
  332. }
  333.  
  334. trg1->t1 = trg;
  335. trg1->t2 = trg->t3;
  336. trg1->t3 = trg->t1;
  337.  
  338. if(trg->t1)
  339. {
  340. trg2->t1 = trg->t1;
  341. trg2->t2 = trg->t1->t3;
  342. trg2->t3 = trg;
  343. if(trg->t1->t3) updateTriangleRef(trg->t1->t3, trg->t1, trg2);
  344. trg->t1->t1 = trg1;
  345. trg->t1->t3 = trg2;
  346.  
  347. pushToRebuild(trg->t1, trg2);
  348. pushToRebuild(trg2, trg);
  349. }
  350.  
  351. pushToRebuild(trg, trg1);
  352. pushToRebuild(trg1, trg->t1);
  353.  
  354. if(trg->t3) updateTriangleRef(trg->t3, trg, trg1);
  355. trg->t1 = trg2;
  356. trg->t3 = trg1;
  357.  
  358. }
  359. rebuildTriangles();
  360. }
  361. __inline int checkEqualNodes(PNODE node, PNODE node1)
  362. {
  363. if(dots_equal(node->crd, node1->crd))
  364. {
  365. addEdge(node->id, node1->id, segm_abs_2(node->crd, node1->crd), 0, 0);
  366. return 1;
  367. }
  368. return 0;
  369. }
  370. void delaunayTriangulation()
  371. {
  372. int i;
  373. PTRIANGLE trg1, trg2;
  374.  
  375. cache_size = 2;
  376. start_queue = 0;
  377. end_queue = 0;
  378. nEdges = 0;
  379. pnexttrg = triangles;
  380. nTriangles = 0;
  381. nodes[nNodes].crd.x = norm.minx;
  382. nodes[nNodes].crd.y = norm.miny;
  383. nodes[nNodes].id = nNodes;
  384.  
  385. nodes[nNodes+1].crd.x = norm.maxx;
  386. nodes[nNodes+1].crd.y = norm.miny;
  387. nodes[nNodes+1].id = nNodes+1;
  388.  
  389. nodes[nNodes+2].crd.x = norm.maxx;
  390. nodes[nNodes+2].crd.y = norm.maxy;
  391. nodes[nNodes+2].id = nNodes+2;
  392.  
  393. nodes[nNodes+3].crd.x = norm.minx;
  394. nodes[nNodes+3].crd.y = norm.maxy;
  395. nodes[nNodes+3].id = nNodes+3;
  396. trg1 = addTriangle(nodes+nNodes, nodes+nNodes+3, nodes+nNodes+1);
  397. trg2 = addTriangle(nodes+nNodes+1, nodes+nNodes+3, nodes+nNodes+2);
  398.  
  399. cache[0][0] = cache[0][1] = trg1;
  400. cache[1][0] = cache[1][1] = trg2;
  401.  
  402. trg1->t1 = trg1->t3 = 0;
  403. trg1->t2 = trg2;
  404. trg2->t2 = trg2->t3 = 0;
  405. trg2->t1 = trg1;
  406. for(i = 0; i< nNodes; i++)
  407. {
  408. trg1 = findTriangle(&nodes[i].crd);
  409. if(checkEqualNodes(trg1->n1, nodes+i) ||
  410. checkEqualNodes(trg1->n2, nodes+i) ||
  411. checkEqualNodes(trg1->n3, nodes+i))
  412. continue;
  413.  
  414. splitTriangle(nodes+i, trg1);
  415.  
  416. if(i >= CACHE_INCREASE_COEF*cache_size*cache_size)
  417. increaseCache();
  418. }
  419. }
  420. __inline int getEdgeMask(PTRIANGLE trg, int startNodeId)
  421. {
  422. if(trg->n1->id == startNodeId) return 1;
  423. if(trg->n2->id == startNodeId) return 2;
  424. if(trg->n3->id == startNodeId) return 4;
  425. return 0;
  426. }
  427.  
  428. void extractEdges()
  429. {
  430. char edgesmap[MAX_TRIANGLES] = {0};
  431. int i = 0;
  432. PTRIANGLE trg;
  433.  
  434. for(i = 0; i < nTriangles; i++)
  435. {
  436. trg = triangles + i;
  437. trg->d1 = segm_abs_2(trg->n1->crd, trg->n2->crd);
  438. trg->d2 = segm_abs_2(trg->n2->crd, trg->n3->crd);
  439. trg->d3 = segm_abs_2(trg->n3->crd, trg->n1->crd);
  440.  
  441. if(trg->n1->id < nNodes && trg->n2->id < nNodes && trg->n3->id < nNodes)
  442. {
  443. if(trg->d1 > trg->d2)
  444. {
  445. if(trg->d1 > trg->d3)
  446. {
  447. if(trg->t1) edgesmap[trg->t1-triangles] |= getEdgeMask(trg->t1, trg->n2->id);
  448. edgesmap[i] |= 1;
  449. }
  450. else
  451. {
  452. if(trg->t3) edgesmap[trg->t3-triangles] |= getEdgeMask(trg->t3, trg->n1->id);
  453. edgesmap[i] |= 4;
  454. }
  455.  
  456.  
  457. }else
  458. {
  459. if(trg->d2 > trg->d3)
  460. {
  461. if(trg->t2) edgesmap[trg->t2-triangles] |= getEdgeMask(trg->t2, trg->n3->id);
  462. edgesmap[i] |= 2;
  463. }
  464. else
  465. {
  466. if(trg->t3) edgesmap[trg->t3-triangles] |= getEdgeMask(trg->t3, trg->n1->id);
  467. edgesmap[i] |= 4;
  468. }
  469. }
  470. }else
  471. {
  472. if(trg->n1->id >= nNodes)
  473. edgesmap[i] |= 5;
  474. if(trg->n2->id >= nNodes)
  475. edgesmap[i] |= 3;
  476. if(trg->n3->id >= nNodes)
  477. edgesmap[i] |= 6;
  478. }
  479.  
  480. if((edgesmap[i] & 1) == 0)
  481. {
  482. addEdge(trg->n1->id, trg->n2->id, trg->d1, trg, trg->t1);
  483. if(trg->t1) edgesmap[trg->t1-triangles] |= getEdgeMask(trg->t1, trg->n2->id);
  484. }
  485. if((edgesmap[i] & 2)==0)
  486. {
  487. addEdge(trg->n2->id, trg->n3->id, trg->d2, trg, trg->t2);
  488. if(trg->t2) edgesmap[trg->t2-triangles] |= getEdgeMask(trg->t2, trg->n3->id);
  489.  
  490. }
  491. if((edgesmap[i] & 4)==0)
  492. {
  493. addEdge(trg->n3->id, trg->n1->id, trg->d3, trg, trg->t3);
  494. if(trg->t3) edgesmap[trg->t3-triangles] |= getEdgeMask(trg->t3, trg->n1->id);
  495. }
  496. }
  497.  
  498. }
  499. __inline int floatcmp( const void *arg1, const void *arg2 )
  500. {
  501. return (*(float*)arg1)<(*(float*)arg2)?-1:(*(float*)arg1)==(*(float*)arg2)?0:1;
  502. }
  503. void findMST(MSTCALLBACK callback)
  504. {
  505. int i, j, q = 0;
  506. short selected[MAX_NODES];
  507.  
  508. for(i = 0; i < nNodes; i++)
  509. selected[i] = i;
  510.  
  511. qsort(edges, nEdges, sizeof(EDGE), floatcmp);
  512.  
  513. for(i = 0; i < nEdges; i++)
  514. {
  515. if(selected[edges[i].n1] != selected[edges[i].n2])
  516. {
  517. int s1 = selected[edges[i].n1],
  518. s2 = selected[edges[i].n2];
  519.  
  520. for(j = 0; j < nNodes; j++)
  521. if(selected[j] == s2) selected[j] = s1;
  522.  
  523. callback(edges + i);
  524.  
  525. q++;
  526. if(q == nNodes - 1)
  527. break;
  528. }
  529. }
  530. }
  531. #define two_edges(a) ((a)>4||(a)==3)
  532. #define triangle_square(a,b,c) ((a).x*((b).y-(c).y)+(b).x*((c).y-(a).y)+(c).x*((a).y-(b).y))/2
  533. #define sqrt32 (float)0.86602540378
  534. __inline int floatrcmp( const void *arg1, const void *arg2 )
  535. {
  536. return (*(float*)arg1)>(*(float*)arg2)?-1:(*(float*)arg1)==(*(float*)arg2)?0:1;
  537. }
  538. int getSteinerPoint(PCOORD crd1, PCOORD crd2, PCOORD crd3, float d1, float d2, float d3, float sqr, PCOORD spoint)
  539. {
  540. COORD P, O, M;
  541. double R2, a1, a2, b1, b2, a, b, c, t;
  542. double e1, e2, e3;
  543. if(d3-d1-d2 > 0.4*sqrt(d1*d2))
  544. return 0;
  545.  
  546. P.y = crd1->x-crd3->x+crd3->y;
  547. P.x = crd3->y-crd1->y+crd3->x;
  548.  
  549. if(dotRelation(&P, crd3, crd1) != LEFT)
  550. {
  551. P.y=-(P.y-crd3->y);
  552. P.x=-(P.x-crd3->x);
  553. }else
  554. {
  555. P.y-=crd3->y;
  556. P.x-=crd3->x;
  557. }
  558. P.x*=sqrt32;
  559. P.y*=sqrt32;
  560. M.x = (crd1->x+crd3->x)/2;
  561. M.y = (crd1->y+crd3->y)/2;
  562. O.x = P.x/3+M.x;
  563. O.y = P.y/3+M.y;
  564. P.x += M.x;
  565. P.y += M.y;
  566. R2 = d3/3;
  567. a1 = crd2->x - P.x;
  568. a2 = crd2->y - P.y;
  569. b1 = P.x - O.x;
  570. b2 = P.y - O.y;
  571. a = sqrt(a1*a1+a2*a2);
  572. a1 /= a;
  573. a2 /= a;
  574. b = a1*b1+a2*b2;
  575. c = b1*b1+b2*b2-R2;
  576. if(b>0)
  577. t = (-b-sqrt(b*b-c));
  578. else
  579. t = (-b+sqrt(b*b-c));
  580.  
  581. spoint->x = P.x + a1*t;
  582. spoint->y = P.y + a2*t;
  583.  
  584. return 1;
  585. }
  586. void findSMT()
  587. {
  588. TRG_SQUARE squares[MAX_TRIANGLES];
  589. PTRIANGLE trg;
  590. int i, nSquares = 0, bExists;
  591.  
  592. for(i =0; i < nEdges; i++)
  593. if(edges[i].d != 0) break;
  594.  
  595. nEdges = i;
  596. nSteinerNodes = nNodes;
  597.  
  598. for(i = 0; i < nTriangles; i++ )
  599. {
  600. trg = triangles+i;
  601. if( two_edges(trg->usedEdges) )
  602. {
  603. squares[nSquares].trg = trg;
  604. squares[nSquares++].sqr = triangle_square(trg->n3->crd, trg->n2->crd, trg->n1->crd);
  605. }
  606. }
  607. qsort(squares, nSquares, sizeof(TRG_SQUARE), floatrcmp);
  608.  
  609. for(i = 0; i < nSquares; i++)
  610. {
  611. trg = squares[i].trg;
  612. if( !two_edges(trg->usedEdges) )
  613. continue;
  614.  
  615. if(trg->usedEdges == 3)
  616. bExists = getSteinerPoint(&trg->n1->crd, &trg->n2->crd, &trg->n3->crd, trg->d1, trg->d2, trg->d3, squares[i].sqr, &nodes[nSteinerNodes].crd);
  617. else if(trg->usedEdges == 5)
  618. bExists = getSteinerPoint(&trg->n3->crd, &trg->n1->crd, &trg->n2->crd, trg->d3, trg->d1, trg->d2, squares[i].sqr, &nodes[nSteinerNodes].crd);
  619. else if(trg->usedEdges == 6)
  620. bExists = getSteinerPoint(&trg->n2->crd, &trg->n3->crd, &trg->n1->crd, trg->d2, trg->d3, trg->d1, squares[i].sqr, &nodes[nSteinerNodes].crd);
  621.  
  622. if(bExists)
  623. {
  624. if(trg->t1) trg->t1->usedEdges &= ~getEdgeMask(trg->t1, trg->n2->id);
  625. if(trg->t2) trg->t2->usedEdges &= ~getEdgeMask(trg->t2, trg->n3->id);
  626. if(trg->t3) trg->t3->usedEdges &= ~getEdgeMask(trg->t3, trg->n1->id);
  627. nodes[nSteinerNodes].id = nSteinerNodes;
  628.  
  629. addEdge(nSteinerNodes, trg->n1->id, 0, 0, 0);
  630. addEdge(nSteinerNodes, trg->n2->id, 0, 0, 0);
  631. addEdge(nSteinerNodes, trg->n3->id, 0, 0, 0);
  632. trg->usedEdges = 0;
  633. nSteinerNodes++;
  634. }
  635. }
  636.  
  637. for(i = 0; i < nTriangles; i++)
  638. {
  639. trg = triangles + i;
  640. if(trg->usedEdges & 1)
  641. {
  642. addEdge(trg->n1->id, trg->n2->id, 0, 0, 0);
  643. if(trg->t1) trg->t1->usedEdges &= ~getEdgeMask(trg->t1, trg->n2->id);
  644. }
  645. if(trg->usedEdges & 2)
  646. {
  647. addEdge(trg->n2->id, trg->n3->id, 0, 0, 0);
  648. if(trg->t2) trg->t2->usedEdges &= ~getEdgeMask(trg->t2, trg->n3->id);
  649. }
  650. if(trg->usedEdges & 4)
  651. {
  652. addEdge(trg->n3->id, trg->n1->id, 0, 0, 0);
  653. if(trg->t3) trg->t3->usedEdges &= ~getEdgeMask(trg->t3, trg->n1->id);
  654. }
  655.  
  656. }
  657.  
  658. }
  659.  
  660. void readData()
  661. {
  662. int i;
  663. scanf("%d", &nNodes);
  664. norm.minx = norm.miny = 100000.0;
  665. norm.maxx = norm.maxy = 0.0;
  666.  
  667. for(i = 0; i < nNodes; i++)
  668. {
  669. scanf("%f %f", &nodes[i].crd.x, &nodes[i].crd.y);
  670. if(nodes[i].crd.x < norm.minx)
  671. norm.minx = nodes[i].crd.x;
  672. if(nodes[i].crd.x > norm.maxx)
  673. norm.maxx = nodes[i].crd.x;
  674. if(nodes[i].crd.y < norm.miny)
  675. norm.miny = nodes[i].crd.y;
  676. if(nodes[i].crd.y > norm.maxy)
  677. norm.maxy = nodes[i].crd.y;
  678. nodes[i].id = i;
  679. }
  680. norm.maxx += 1;
  681. norm.maxy += 1;
  682. norm.minx -= 1;
  683. norm.miny -= 1;
  684. norm.divx = (norm.maxx - norm.minx);
  685. norm.divy = (norm.maxy - norm.miny);
  686. }
  687.  
  688.  
  689. void mstCallback(PEDGE pEdge)
  690. {
  691. if(pEdge->trg1) pEdge->trg1->usedEdges |= getEdgeMask(pEdge->trg1, pEdge->n1);
  692. if(pEdge->trg2) pEdge->trg2->usedEdges |= getEdgeMask(pEdge->trg2, pEdge->n2);
  693. }
  694. void writeData()
  695. {
  696. int i;
  697. printf("%d\n", nSteinerNodes - nNodes);
  698. for(i = nNodes; i < nSteinerNodes; i++)
  699. {
  700. printf("%f %f\n", nodes[i].crd.x, nodes[i].crd.y);
  701. }
  702. printf("%d\n", nEdges);
  703. for(i = 0 ; i < nEdges; i++)
  704. {
  705. printf("%d %d\n", edges[i].n1, edges[i].n2);
  706. }
  707. }
  708.  
  709.  
  710. int main()
  711. {
  712. int t;
  713.  
  714. scanf("%d", &t);
  715. while(t--)
  716. {
  717. readData();
  718. delaunayTriangulation();
  719. extractEdges();
  720. findMST(mstCallback);
  721. findSMT();
  722. writeData();
  723. }
  724. return 0;
  725. }