diff --git a/algorithms/graph/floyd_warshall.cpp b/algorithms/graph/floyd_warshall.cpp index d84545f831be5a1e548520c9e4f087e692c00db9..528d1a667a774ef04c7e5611b28224026ff24331 100644 --- a/algorithms/graph/floyd_warshall.cpp +++ b/algorithms/graph/floyd_warshall.cpp @@ -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]); } }; diff --git a/algorithms/math/gale_shapley.cpp b/algorithms/math/gale_shapley.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6009274b8ffcc675b34e5a65f9d3e708d52c308f --- /dev/null +++ b/algorithms/math/gale_shapley.cpp @@ -0,0 +1,70 @@ +/// 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; +} diff --git a/algorithms/structure/segment_tree.cpp b/algorithms/structure/segment_tree.cpp index 3eb3784c5e233734d4c839f9baf6312ac723ae3f..77f82655b21bf2de8195f4f6c07de1a88dc54875 100644 --- a/algorithms/structure/segment_tree.cpp +++ b/algorithms/structure/segment_tree.cpp @@ -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); diff --git a/caderno.pdf b/caderno.pdf index 53d0190a3a5725ada0d5ed98b3b139107b0916d9..0be09685d4ca6d5c8ad92e21ee518a0f3077b01d 100644 Binary files a/caderno.pdf and b/caderno.pdf differ diff --git a/contests/Cadernaveis/URI1852.cpp b/contests/Cadernaveis/URI1852.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f33593107155cfa994cdfeb9b17ded41735ba72f --- /dev/null +++ b/contests/Cadernaveis/URI1852.cpp @@ -0,0 +1,115 @@ +#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; +}