Skip to content

Commit b9e5f96

Browse files
committed
Copied Hungarian Algorithm from Wikipedia
I still do not understand it tho...
1 parent 486c136 commit b9e5f96

3 files changed

Lines changed: 106 additions & 0 deletions

File tree

4/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
add_executable(hungarian_algorithm hungarian_algorithm.cpp)
2+
target_link_libraries(hungarian_algorithm PRIVATE mimalloc)

4/hungarian_algorithm.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#if __has_include(<mimalloc-new-delete.h>)
2+
#include <mimalloc-new-delete.h>
3+
#endif
4+
5+
#if __has_include(<mdspan>)
6+
#include <mdspan>
7+
#else
8+
#include "util/mdspan.hpp"
9+
#endif
10+
11+
#include <algorithm>
12+
#include <iostream>
13+
#include <limits>
14+
#include <vector>
15+
16+
using namespace std;
17+
18+
using Weight = int32_t;
19+
20+
constexpr int INF = numeric_limits<Weight>::max();
21+
22+
pair<Weight, vector<int>> hungarian(const vector<vector<Weight>>& cost) {
23+
auto n = cost.size();
24+
vector<int> u(n, 0); // Labels do U
25+
vector<int> v(n, 0); // Labels do V
26+
vector<int> match_left(n, -1);
27+
vector<int> match_right(n, -1);
28+
29+
for (int i = 0; i < n; ++i) {
30+
vector<int> effective_costs(n, INF);
31+
vector<int> predecessors(n, -1);
32+
vector used(n, false);
33+
34+
int marked_i = i;
35+
int marked_j = -1;
36+
int j;
37+
38+
while (true) {
39+
j = -1;
40+
for (int k = 0; k < n; ++k) {
41+
if (!used[k]) {
42+
auto effective_cost = cost[marked_i][k] - u[marked_i] - v[k];
43+
if (effective_cost < effective_costs[k]) {
44+
effective_costs[k] = effective_cost;
45+
predecessors[k] = marked_j;
46+
}
47+
if (j == -1 || effective_costs[k] < effective_costs[j])
48+
j = k;
49+
}
50+
}
51+
52+
int delta = effective_costs[j];
53+
for (int k = 0; k < n; ++k) {
54+
if (used[k]) {
55+
u[match_right[k]] += delta;
56+
v[k] -= delta;
57+
} else {
58+
effective_costs[k] -= delta;
59+
}
60+
}
61+
u[i] += delta;
62+
63+
used[j] = true;
64+
marked_j = j;
65+
if (match_right[j] == -1) {
66+
break;
67+
}
68+
marked_i = match_right[j];
69+
}
70+
71+
while (predecessors[j] != -1) {
72+
match_right[j] = match_right[predecessors[j]];
73+
j = predecessors[j];
74+
}
75+
match_right[j] = i;
76+
}
77+
78+
// Monta match_left
79+
int total_weight = 0;
80+
for (int j = 0; j < n; ++j) {
81+
if (match_right[j] != -1) {
82+
match_left[match_right[j]] = j;
83+
total_weight += cost[match_right[j]][j];
84+
}
85+
}
86+
87+
return {total_weight, match_left};
88+
}
89+
90+
int main() {
91+
vector<vector<Weight>> weight = {{10, 19, 8}, {10, 18, 7}, {5, 7, 9}};
92+
93+
auto [max_weight, match] = hungarian(weight);
94+
95+
cout << "Emparelhamento ótimo (máximo peso):\n";
96+
for (int i = 0; i < match.size(); ++i) {
97+
cout << "Vértice " << i << " emparelhado com " << match[i]
98+
<< " (peso: " << weight[i][match[i]] << ")\n";
99+
}
100+
cout << "Peso total do emparelhamento: " << max_weight << endl;
101+
102+
return 0;
103+
}

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@ find_package(OpenMP REQUIRED)
3737
add_subdirectory(1)
3838
add_subdirectory(2)
3939
add_subdirectory(3)
40+
add_subdirectory(4)

0 commit comments

Comments
 (0)