StableMatchings.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // stable marriage O(n2)
  2. int L, R;
  3. int L_pref[MAX_L][MAX_R], R_rank[MAX_R][MAX_L];
  4. int L2R[MAX_L], R2L[MAX_R];
  5. int p[MAX_L]; // id of the best R in L_pref the l can get
  6. void stable_marriage () {
  7. fill_n(R2L, R, -1);
  8. fill_n(p, L, 0);
  9. for (int i = 0; i < L; i++)
  10. for (int l = i; l >= 0;) {
  11. int r = L_pref[l][p[l]++];
  12. if (R2L[r] < 0 || R_rank[r][l] < R_rank[r][R2L[r]]) {
  13. int old_l = R2L[r];
  14. R2L[L2R[l] = r] = l;
  15. l = old_l;
  16. }
  17. }
  18. }
  19. // hospital resident (mariage stable polygame) O(n2)
  20. /*
  21. RO : needed for Resident -Oriented version
  22. HO : needed for Hospital -Oriented version
  23. */
  24. // Input data
  25. int R, H; // Number of Residents/Hospitals
  26. int C[MAX_H]; // Capacity of hospitals
  27. vector <int > R_pref[MAX_R], H_pref[MAX_H]; // Preferences : adjency lists
  28. /*RO*/int H_rank[MAX_H][MAX_R]; // Rank : rank of r in H_pref[h]
  29. /*HO*/int R_rank[MAX_R][MAX_H]; // Rank : rank of h in R_pref[r]
  30. // Internal data
  31. int RankWorst[MAX_H]; // Rank of the worst r taken by h
  32. /*RO*/int BestH[MAX_R]; // Indice of the best h in R_pref the r can get
  33. /*HO*/int BestR[MAX_H]; // Indice of the best r in H_pref the h can get
  34. int Size[MAX_H]; // Number of residents taken by h
  35. // Output data
  36. int M[MAX_R];
  37. void stable_hospitals_RO () {
  38. for (int h = 0; h < H; h++)
  39. RankWorst[h] = H_pref[h].size() - 1;
  40. fill_n(BestH, R, 0);
  41. fill_n(Size, H, 0);
  42. fill_n(M, R, INF);
  43. for (int i = 0; i < R; i++)
  44. for (int r = i; r >= 0;) {
  45. if (BestH[r] == int(R_pref[r].size()))
  46. break;
  47. const int h = R_pref[r][BestH[r]++];
  48. if (Size[h]++ < C[h]) {
  49. M[r] = h;
  50. break;
  51. }
  52. int WorstR = H_pref[h][RankWorst[h]];
  53. while (WorstR == INF || M[WorstR] != h) // Compute the worst
  54. WorstR = H_pref[h][--RankWorst[h]];
  55. if (H_rank[h][r] < RankWorst[h]) { // Ranked better that worst
  56. M[r] = h;
  57. M[r = WorstR] = INF; // We have eliminated it, he need to put it somewhere
  58. }
  59. }
  60. }
  61. void stable_hospitals_HO () {
  62. fill_n(BestR, H, 0);
  63. fill_n(Size, H, 0);
  64. fill_n(M, R, INF);
  65. VI SH;
  66. for (int h = 0; h < H; h++)
  67. SH.push_back(h);
  68. while (!SH.empty()) {
  69. int h = SH.back();
  70. if (Size[h] == C[h] || BestR[h] == int(H_pref[h].size())) { // Full or no r
  71. // available
  72. SH.pop_back();
  73. break;
  74. }
  75. const int r = H_pref[h][BestR[h]++];
  76. // r is unassigned or prefer h to current hospital
  77. if (M[r] == INF || R_rank[r][h] < R_rank[r][M[r]]) {
  78. Size[h]++;
  79. if (Size[h] == C[h]) // Will be full
  80. SH.pop_back();
  81. if (M[r] != INF) { // Delete from M[r]
  82. Size[M[r]]--;
  83. SH.push_back(M[r]);
  84. }
  85. M[r] = h;
  86. }
  87. }
  88. }
  89. // stable roomate (mariage stable homosexuel) O(n2)
  90. const int MAX_N = 1000;
  91. int N; // Entree : Nombre de colocataires
  92. int M[MAX_N][MAX_N]; // Entree : Liste de preferences de chaque colocataire
  93. int rank[MAX_N][MAX_N];
  94. int pos[MAX_N][3]; // Positions of left -most , second , right -most
  95. int found[MAX_N];
  96. int Match[MAX_N]; // Sortie : Matching recherche
  97. bool Matching () {
  98. // Phase 1
  99. for (int i = 0; i < N; i++) {
  100. M[i][N - 1] = i; // Sentinel
  101. for (int j = 0; j < N; j++)
  102. rank[i][M[i][j]] = j;
  103. pos[i][0] = 0;
  104. pos[i][2] = N - 1;
  105. }
  106. for (int p = 0; p < N; p++) {
  107. int next, current, prop = p;
  108. do {
  109. next = M[prop][pos[prop][0]];// next to propose to
  110. current = M[next][pos[next][2]];// next has proposition from
  111. // next is better with current:
  112. while (rank[next][prop] > rank[next][current]) {
  113. pos[prop][0]++; // Let ’s try the next one
  114. next = M[prop][pos[prop][0]];
  115. current = M[next][pos[next][2]];
  116. }
  117. pos[next][2] = rank[next][prop];// Update data
  118. prop = current;// This one just loose its proposal
  119. }
  120. while (current != next);// next was associated with current , ie himself
  121. }
  122. for (int i = 0; i < N; i++)
  123. pos[i][1] = pos[i][0] + 1;
  124. // Phase 2
  125. vector <int> path;
  126. fill_n(found, N, -1);
  127. for (int i = 0; i < N; i++) {
  128. path.push_back(i);
  129. while (!path.empty()) {
  130. int p = path.back(), size;
  131. if (pos[p][0] == pos[p][2]) {
  132. const int q = M[p][pos[p][0]];
  133. Match[Match[q] = p] = q;
  134. path.pop_back();
  135. continue;
  136. }
  137. found[p] = -1; // Force exploration (might be != -1 from before)
  138. while (found[p] == -1) { // Find cycle
  139. found[p] = path.size(); // Register it
  140. int nd = M[p][pos[p][1]]; // Second
  141. while (pos[nd][2] < rank[nd][p])
  142. nd = M[p][++pos[p][1]];
  143. path.push_back(p = M[nd][pos[nd][2]]);
  144. }
  145. for (int i = size = found[p]; i < (int) path.size(); i++) {
  146. found[p = path[i]] = -1;
  147. pos[p][0] = pos[p][1]++; // p refuses it’s first proposal
  148. const int q = M[p][pos[p][0]];
  149. pos[q][2] = rank[q][p]; // Propagate association
  150. if (pos[q][0] > pos[q][2]) // No solution
  151. return false;
  152. }
  153. path.resize(size - 1); // 1 5 4 [2 3 4] ==> found[p] = 3 ==> 1 5
  154. }
  155. }
  156. return true;
  157. }