Skip to content
Snippets Groups Projects
Commit 62a357ae authored by Bruno Freitas Tissei's avatar Bruno Freitas Tissei
Browse files

Add Gale-Shapley algorithm

parent 5674d77d
No related branches found
No related tags found
No related merge requests found
......@@ -12,7 +12,7 @@ struct FloydWarshall {
FloydWarshall(int N) :
N(N) {}
int run() {
void run() {
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
dist[i][j] = graph[i][j];
......@@ -21,6 +21,6 @@ struct FloydWarshall {
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
dist[i][j] = min(dist[i][j],
dist[i][k] + dist[k][j])
dist[i][k] + dist[k][j]);
}
};
/// Gale-Shapley (Stable Marriage)
///
/// Description:
/// Two groups, each of size N are given: men and women. Each person has a
/// list of preference ranking all N people of the opposite sex. The task is to
/// unite both groups into stable pairs. A set of pairs is stable if there are
/// no unassigned couple that like each other more than their assigned pair.\par
/// The algorithm's steps are: 1) allow every men to propose to their highest
/// ranking woman; 2) the women become tentatively engaged to their top choice
/// of men; 3) all rejected men propose to their next choice; 4) the woman
/// replaces their current pair in case a man with a higher rank proposes to
/// her, the replaced men are now marked as rejected; 5) repeat step 3 until
/// all men are paired.
///
/// Time: O(n^2)
/// Space: O(n^2)
///
/// Caution:
/// - Men are indexed by [0..N)
/// - Women are indexed by [N..2N)
/// - The result prioritizes men, swapping the bottom half
/// of the matrix by the top half will invert who's given
/// preference
///
/// Status: Tested (URI1852)
// Receives matrix of preferences pref[2*N][N] and returns
// vector v where v[m] contains preference of the m-th man.
vector<int> gale_shapley(const vector<vector<int>> &pref) {
int n = pref[0].size();
vector<int> w_part(n, -1);
vector<int> m_part(n, -1);
vector<int> start(n, 0);
while (true) {
int m;
for (m = 0; m < n; ++m)
if (m_part[m] == -1)
break;
if (m == n) break;
for (; start[m] < n && m_part[m] == -1; ++start[m]) {
int w = pref[m][start[m]];
if (w_part[w - n] == -1) {
w_part[w - n] = m;
m_part[m] = w;
} else {
int m1 = w_part[w - n];
bool pref_m = false;
for (int j = 0; j < n; ++j)
if (pref[w][j] == m) {
pref_m = true;
break;
} else if (pref[w][j] == m1)
break;
if (pref_m) {
w_part[w - n] = m;
m_part[m] = w;
m_part[m1] = -1;
}
}
}
}
return m_part;
}
......@@ -4,42 +4,37 @@
/// - update: O(log n)
/// - query: O(log n)
/// Space: O(n)
///
/// Caution:
/// - Query returns op([l..r))
/// - Provide identity value if necessary (default is T())
// Example: SegmentTree<int,plus<int>> seg(n)
template <typename T, typename OpType = T(*)(T&, T&)>
struct SegmentTree {
int N;
vector<int> tree;
Tree(int N) :
N(N), tree(2 * N, 0) {}
T ident;
OpType op;
vector<T> tree;
// Base depends on 'op':
// op: a + b -> base: 0
// op: min(a,b) -> base: inf
int base = -inf;
int op(int a, int b) {
return max(a, b);
}
SegmentTree(int N, T ident = T()) :
N(N), ident(ident), tree(2 * N, ident) {}
void update(int idx, int val) {
void update(int idx, T val) {
idx += N;
tree[idx] = val;
while (idx > 1) {
tree[idx / 2] = op(tree[idx & ~1], tree[idx | 1]);
idx /= 2;
}
for (; idx > 1; idx >>= 1)
tree[idx >> 1] = op(tree[idx & ~1], tree[idx | 1]);
}
int query(int l, int r) {
int ra = base, rb = base;
T query(int l, int r) {
T ra = ident, rb = ident;
l += N, r += N;
while (l < r) {
if (l % 2) ra = op(ra, tree[l++]);
if (r % 2) rb = op(tree[--r], rb);
l >>= 1;
r >>= 1;
for (; l < r; l >>= 1, r >>= 1) {
if (l & 1) ra = op(ra, tree[l++]);
if (r & 1) rb = op(tree[--r], rb);
}
return op(ra, rb);
......
No preview for this file type
#include <bits/stdc++.h>
#define EPS 1e-6
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define fi first
#define se second
#define pb push_back
#define ende '\n'
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define mset(x, y) memset(&x, (y), sizeof(x))
using namespace std;
using ll = long long;
using ii = pair<int,int>;
vector<int> gale_shapley(const vector<vector<int>> &pref) {
int n = pref[0].size();
vector<int> w_part(n, -1);
vector<int> m_part(n, -1);
vector<int> start(n, 0);
while (true) {
int m;
for (m = 0; m < n; ++m)
if (m_part[m] == -1)
break;
if (m == n) break;
for (; start[m] < n && m_part[m] == -1; ++start[m]) {
int w = pref[m][start[m]];
if (w_part[w - n] == -1) {
w_part[w - n] = m;
m_part[m] = w;
} else {
int m1 = w_part[w - n];
bool pref_m = false;
for (int j = 0; j < n; ++j)
if (pref[w][j] == m) {
pref_m = true;
break;
} else if (pref[w][j] == m1)
break;
if (pref_m) {
w_part[w - n] = m;
m_part[m] = w;
m_part[m1] = -1;
}
}
}
}
return m_part;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n; cin >> n;
vector<vector<int>> pref(2*n, vector<int>(n));
int k1 = 0, k2 = n;
map<string,int> M;
vector<string> names(2*n);
for (int i = 0; i < n; ++i) {
string s; cin >> s;
if (M.find(s) == M.end()) {
names[k1] = s;
M[s] = k1++;
}
for (int j = 0; j < n; ++j) {
string t; cin >> t;
if (M.find(t) == M.end()) {
names[k2] = t;
M[t] = k2++;
}
pref[M[s]][j] = M[t];
}
}
for (int i = 0; i < n; ++i) {
string s; cin >> s;
if (M.find(s) == M.end()) {
names[k2] = s;
M[s] = k2++;
}
for (int j = 0; j < n; ++j) {
string t; cin >> t;
if (M.find(t) == M.end()) {
names[k1] = t;
M[t] = k1++;
}
pref[M[s]][j] = M[t];
}
}
vector<int> ans = gale_shapley(pref);
for (int i = 0; i < n; ++i)
cout << names[i] << " " << names[ans[i]] << ende;
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment