Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
4.9 KiB

  1. /******************************************************************************
  2. *
  3. * LHMatch Online
  4. *
  5. * Authors: Nicholas Harvey and Laszlo Lovasz
  6. *
  7. * Developed: April 2001
  8. *
  9. * Algorithm Description:
  10. *
  11. * Let S be {}
  12. * Let M be {}
  13. * While S != U Do
  14. * Assert( S is a subset of U )
  15. * Assert( M is an optimal LH matching of G restricted to S \union V )
  16. * Let x \member U \ S
  17. * For each edge (u,v) in E
  18. * If (u,v) \member M, orient this edge from v to u
  19. * Else, orient this edge from u to v
  20. * Build a directed breadth-first search tree rooted at x
  21. * Let y be a vertex in the BFS tree \intersection V with minimum M-degree
  22. * Alternate along the unique x->y dipath, increasing the size of M by one
  23. * Add x to S
  24. * Repeat
  25. *
  26. * This algorithm is called online because the optimality of the matching is
  27. * maintained as the size increases.
  28. *
  29. * Runtime:
  30. *
  31. * The worst-case runtime is O(|U| * |E|), but in practice it is quite slow.
  32. *
  33. ******************************************************************************/
  34. /***** Header Files *****/
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <assert.h>
  39. #include "LHMatchInt.h"
  40. /***** EnqueueNbr *****/
  41. /* Enqueue all neigbours of this vertex which have not yet been visited.
  42. * If 'matchedOnly' is true, enqueue only the matched-neigbours. */
  43. static void EnqueueNbr(Graph *g, Vertex *v, char matchedOnly) {
  44. Vertex *n;
  45. int i;
  46. for(i=0;i<v->degree;i++) {
  47. n=v->adjList[i];
  48. if( !matchedOnly || n->matchedWith==v ) {
  49. if( n->parent==NULL ) {
  50. DPRINT( printf("Adding %d to queue with parent %d\n",n->id,v->id); )
  51. g->Queue[g->Qsize++]=n;
  52. n->parent=v;
  53. } else {
  54. DPRINT( printf("Not adding %d to queue -- already there\n",n->id); )
  55. }
  56. }
  57. }
  58. }
  59. /***** UpdateMinRHSLoad *****/
  60. static void UpdateMinRHSLoad(Graph *g) {
  61. int i;
  62. g->minRHSLoad = g->numLHSVtx;
  63. for(i=0;i<g->numRHSVtx;i++) {
  64. g->minRHSLoad = INTMIN(g->minRHSLoad,g->rVtx[i].numMatched);
  65. }
  66. }
  67. /***** AugmentPath *****/
  68. /* Found an augmenting path. Switch the matching edges along it. */
  69. static void AugmentPath(Graph *g, Vertex *u, Vertex *v) {
  70. Vertex *w,*p;
  71. DPRINT( printf("V: %d. Increase load to %d\n", v->id, v->numMatched+1 ); )
  72. /* Switch along the path */
  73. w=v;
  74. w->numMatched++;
  75. do {
  76. p=w->parent;
  77. p->matchedWith=w;
  78. w=p->parent;
  79. } while(p!=u);
  80. assert(w==p);
  81. /* Update minRHSLoad */
  82. if( v->numMatched==g->minRHSLoad+1 ) {
  83. UpdateMinRHSLoad(g);
  84. }
  85. }
  86. /***** BFS *****/
  87. /* Perform a breadth-first search rooted at node i. */
  88. static Vertex* BFS(Graph *g,Vertex *u) {
  89. Vertex *bestV,*v;
  90. int q;
  91. /* Start a BFS from u */
  92. DPRINT( printf("Using %d as root\n",u->id); )
  93. u->parent=u;
  94. g->Queue[0]=u; g->Qsize=1;
  95. bestV=NULL;
  96. /* Process the vertices in the queue */
  97. for(q=0;q<g->Qsize;q++) {
  98. v = g->Queue[q];
  99. DPRINT( printf("Dequeued %d: ",v->id); )
  100. if(IS_LHS_VTX(v)) {
  101. /* Its a LHS-vertex; enqueue all neigbours */
  102. DPRINT( printf("LHS -> Enqueuing all nbrs\n"); )
  103. EnqueueNbr(g, v, FALSE);
  104. } else {
  105. /* Its a RHS-vertex; enqueue all matched-neighbours */
  106. DPRINT( printf("RHS -> Enqueuing all %d matched-nbrs\n",
  107. v->numMatched); )
  108. EnqueueNbr(g, v, TRUE);
  109. if( NULL==bestV || v->numMatched<bestV->numMatched ) {
  110. bestV=v;
  111. if( v->numMatched==g->minRHSLoad ) {
  112. /* v has the minimum M-degree out of all RHS vertices.
  113. * We can stop the BFS prematurely. */
  114. break;
  115. }
  116. }
  117. }
  118. }
  119. return bestV;
  120. }
  121. /***** LHAlgOnline *****/
  122. int LHAlgOnline(Graph *g) {
  123. Vertex *bestV;
  124. int i,j,err;
  125. DPRINT( printf("--- LHMatch Online Started ---\n"); )
  126. g->minRHSLoad=0;
  127. err = InitializeQueue(g);
  128. if( LH_SUCCESS!=err ) {
  129. return err;
  130. }
  131. UpdateMinRHSLoad(g);
  132. /* Examine every vtx on LHS */
  133. for(i=0;i<g->numLHSVtx;i++) {
  134. /* Build a BFS tree and find the best augmenting path */
  135. bestV = BFS(g,&(g->lVtx[i]));
  136. /* If bestV is null, lVtx[i] must have degree 0 */
  137. if( NULL!=bestV ) {
  138. DPRINT( printf("Best aug. path is from %d to %d\n",g->lVtx[i].id,bestV->id); )
  139. AugmentPath(g,&(g->lVtx[i]),bestV);
  140. }
  141. /* Clear the marks on all nodes in the BFS tree */
  142. for(j=0;j<g->Qsize;j++) {
  143. g->Queue[j]->parent=NULL;
  144. }
  145. }
  146. DestroyQueue(g);
  147. DPRINT( printf("--- LHMatch Online Finished ---\n"); )
  148. return LH_SUCCESS;
  149. }