#include <vector>
#include <limits>
#include <algorithm>

class Hungarian {
public:
    Hungarian(const std::vector<std::vector<float>>& costMatrix)
        : n(costMatrix.size()), m(costMatrix[0].size()),
          cost(costMatrix), u(n + 1), v(m + 1),
          p(m + 1), way(m + 1) {}

    // Returns assignment vector: assignment[i] = j
    std::vector<int> solve() {
        for (int i = 1; i <= n; i++) {
            p[0] = i;
            int j0 = 0;
            std::vector<float> minv(m + 1, std::numeric_limits<float>::max());
            std::vector<char> used(m + 1, false);
            do {
                used[j0] = true;
                int i0 = p[j0], j1 = 0;
                float delta = std::numeric_limits<float>::max();
                for (int j = 1; j <= m; j++) {
                    if (!used[j]) {
                        float cur = cost[i0 - 1][j - 1] - u[i0] - v[j];
                        if (cur < minv[j]) {
                            minv[j] = cur;
                            way[j] = j0;
                        }
                        if (minv[j] < delta) {
                            delta = minv[j];
                            j1 = j;
                        }
                    }
                }
                for (int j = 0; j <= m; j++) {
                    if (used[j]) {
                        u[p[j]] += delta;
                        v[j] -= delta;
                    } else {
                        minv[j] -= delta;
                    }
                }
                j0 = j1;
            } while (p[j0] != 0);
            do {
                int j1 = way[j0];
                p[j0] = p[j1];
                j0 = j1;
            } while (j0);
        }
        std::vector<int> assignment(n, -1);
        for (int j = 1; j <= m; j++) {
            if (p[j] != 0) {
                assignment[p[j] - 1] = j - 1;
            }
        }
        return assignment;
    }

private:
    int n, m;
    std::vector<std::vector<float>> cost;
    std::vector<float> u, v;
    std::vector<int> p, way;
};
