Content deleted Content added
(6 intermediate revisions by 4 users not shown) | |||
Line 148:
*/
import std;
template <typename T, typename U>
using Pair = std::pair;▼
using
template <typename T>
template <typename T>
using NumericLimits = std::numeric_limits<T>;
/**
* @brief Checks if b < a
*
* Sets a = min(a, b)
* @param a The first parameter to check
* @param b The second parameter to check
* @tparam The type to perform the check on
* @return true if b < a
*/
template <typename T>
constexpr bool ckmin(T& a, const T& b) {
return b < a ? a = b,
}
/**
* @brief Performs the Hungarian algorithm.
*
* Given J jobs and W workers (J <= W), computes the minimum cost to assign each
* prefix of jobs to distinct workers.
Line 188 ⟶ 200:
// -yt[W] will equal the sum of all deltas
Vector<T> answers;
const T inf =
for (int jCur = 0; jCur < J; ++jCur) { // assign jCur-th job
int wCur = W;
Line 194 ⟶ 206:
// min reduced cost over edges from Z to worker w
Vector<T> minTo(W + 1, inf);
Vector<int>
Vector<bool> inZ(W + 1); // whether worker is in Z
while (job[wCur] != -1) { // runs at most jCur + 1 times
const int j = job[wCur];
T delta = inf;
Line 204 ⟶ 216:
if (!inZ[w]) {
if (ckmin(minTo[w], C[j][w] - ys[j] - yt[w]))
if (ckmin(delta, minTo[w]))
wNext = w;
}
}
Line 223 ⟶ 236:
// update assignments along alternating path
for (int w; wCur != W; wCur = w)
job[wCur] = job[w =
answers.push_back(-yt[W]);
}
Line 230 ⟶ 243:
/**
* @brief Performs a sanity check for the Hungarian algorithm.
*
* Sanity check: https://en.wikipedia.org/wiki/Hungarian_algorithm#Example
* First job (5):
Line 243 ⟶ 258:
void sanityCheckHungarian() {
Vector<Vector<int>> costs{{8, 5, 9}, {4, 2, 4}, {7, 3, 8}};
assert((hungarian(costs) ==
std::println(stderr, "Sanity check passed.");
}
/**
*/
void cordonBleu() {
int N;
Line 256 ⟶ 273:
Vector<Pair<int, int>> bottles(N);
Vector<Pair<int, int>> couriers(M);
for (const Pair<int, int>& b
std::cin >> b.first >> b.second;
for (const Pair<int, int>& c
std::cin >> c.first >> c.second;
Pair<int, int> rest;
Line 275 ⟶ 292:
}
/**
* @brief Entry point into the program.
*
* @return The return code of the program.
*/
int main() {
sanityCheckHungarian();
Line 304 ⟶ 326:
<syntaxhighlight lang="cpp" line="1">
template <typename T>
const int J =
const int W = static_cast<int>(C[0].size());
assert(J <= W);
// job[w] = job assigned to w-th worker, or -1 if no job assigned
// note: a W-th worker was added for convenience
T
const T inf =
// assign
for (int
int
job[
dist[W] = 0;
while (job[
T
vis[
int
// consider extending shortest path by
for (int w = 0; w < W; ++w) {
if (!vis[w]) {
// sum of reduced edge weights
T edge = C[job[
if (
edge -= C[job[
assert(edge >= 0); // consequence of Johnson potentials
}
if (ckmin(dist[w], dist[
if (ckmin(minDist, dist[w]))
wNext = w;
}
}
}
for (int w = 0; w < W; ++w) { // update potentials
ckmin(dist[w], dist[
h[w] += dist[w];
}
ans_cur += h[
for (int w;
answers.push_back(ansCur);
}
return answers;
Line 543 ⟶ 570:
If the number of starred zeros is {{mvar|n}} (or in the general case <math>min(n,m)</math>, where {{mvar|n}} is the number of people and {{mvar|m}} is the number of jobs), the algorithm terminates. See the [[#Result|Result]] subsection below on how to interpret the results.
Otherwise, find the lowest uncovered value. Subtract this from every
This is equivalent to subtracting a number from all rows which are not covered and adding the same number to all columns which are covered. These operations do not change optimal assignments.
|