-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsol3.cpp
More file actions
127 lines (114 loc) · 3.3 KB
/
Copy pathsol3.cpp
File metadata and controls
127 lines (114 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <iostream>
#include <utility>
#include <vector>
#include <list>
#include <unordered_map>
using namespace std;
/**
* Kuhn-Munkres / Hungarian
*
* GIVEN a n * m cost matrix A (limit: ~40x40)
* WHERE n <= m (!!!)
* AND form of matrix equals:
* 0 0 0 0 <-- row 0 and col 0 is padding for data
* 0 INF 3 2 <-- costs of matching i to j
* 0 4 INF 8
* 0 3 3 INF
* RETURNS the minimal cost matching between n and m
* AND the pairs which were matched
*
* Note: A can have negative edge weights and T in {double, int-like}
*/
template <class T>
pair<T, vector<pair<int, int>>> hungarian(const vector<vector<T>> &A)
{
T INF = 1000 * 1000 * 1000; // TODO: update your INF here!
int n = A.size() - 1, m = A[0].size() - 1;
vector<T> pot_row(n + 1), pot_col(m + 1);
vector<int> pairing(m + 1), way(m + 1);
for (int row = 1; row <= n; ++row)
{
pairing[0] = row;
int cur_col = 0;
vector<T> max_pot(m + 1, -INF);
vector<char> used(m + 1, false);
do
{
used[cur_col] = true;
int current_row_match = pairing[cur_col];
int col_with_max;
T delta = INF;
for (int col = 1; col <= m; ++col)
{
if (!used[col])
{
T pot = A[current_row_match][col] + pot_row[current_row_match] + pot_col[col];
if (pot > max_pot[col])
{
max_pot[col] = pot;
way[col] = cur_col;
}
if (max_pot[col] > delta)
{
delta = max_pot[col];
col_with_max = col;
}
}
}
for (int col = 0; col <= m; ++col)
if (used[col])
pot_row[pairing[col]] -= delta, pot_col[col] += delta;
else
max_pot[col] += delta;
cur_col = col_with_max;
} while (pairing[cur_col] != 0);
do
{
int col_with_max = way[cur_col];
pairing[cur_col] = pairing[col_with_max];
cur_col = col_with_max;
} while (cur_col);
}
vector<pair<int, int>> result;
for (int col = 1; col <= m; ++col)
result.push_back(make_pair(pairing[col], col));
return {-pot_col[0], result};
}
int main()
{
int n, m, r;
cin >> n >> m >> r;
int INF = 1000 * 1000 * 1000;
int s = max(n, m);
vector<vector<long long>> M(s + 1, vector<long long>(s + 1, -INF));
for (int i = 0; i < s + 1; ++i)
{
M[i][i] = -INF;
M[0][i] = 0;
M[i][0] = 0;
}
for (int i = 0; i < r; ++i)
{
int u, v, value;
cin >> u >> v >> value;
M[u][v] = -value;
}
pair<int, vector<pair<int, int>>> result = hungarian(M);
cout << result.first << endl;
int answer = 0;
int unmatched = 0;
for (auto &each : result.second)
{
int edge_weight = M[each.first][each.second];
if (edge_weight == 0)
{
unmatched += 1;
}
else
{
answer -= edge_weight;
}
cout << each.first << " , " << each.second << endl;
}
cout << unmatched << " " << answer << endl;
}