Cod sursa(job #3189870)

Utilizator mariapreda19Preda Maria mariapreda19 Data 6 ianuarie 2024 16:39:44
Problema Cc Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.6 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>

class Graf {
    int numarNoduri;
    std::vector<std::vector<int>> capacitati;
    std::vector<std::vector<int>> costuri;
    std::vector<std::vector<int>> flux;

public:
    explicit Graf(int numarNoduri) : numarNoduri(numarNoduri) {
        capacitati.resize(numarNoduri);
        costuri.resize(numarNoduri);
        flux.resize(numarNoduri);

        for (int i = 0; i < numarNoduri; i++) {
            capacitati[i].resize(numarNoduri, 0);
            costuri[i].resize(numarNoduri, 0);
            flux[i].resize(numarNoduri, 0);
        }
    }

    void adaugaCapacitate(int x, int y, int capacitate, int cost) {
        capacitati[x][y] = capacitate;
        capacitati[y][x] = 0;
        costuri[x][y] = cost;
        costuri[y][x] = -cost;
    }

    bool dijkstra(int sursa, int destinatie, std::vector<int>& tati) {
        std::vector<int> distante(numarNoduri, INT_MAX);
        distante[sursa] = 0;
        std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<std::pair<int, int>>> pq;
        pq.push({0, sursa});

        while (!pq.empty()) {
            int nod = pq.top().second;
            int distantaNod = pq.top().first;
            pq.pop();

            if (distantaNod > distante[nod]) {
                continue;
            }

            for (int vecin = 0; vecin < numarNoduri; vecin++) {
                if (capacitati[nod][vecin] - flux[nod][vecin] > 0 &&
                    distante[nod] != INT_MAX &&
                    distante[nod] + costuri[nod][vecin] < distante[vecin]) {
                    distante[vecin] = distante[nod] + costuri[nod][vecin];
                    tati[vecin] = nod;
                    pq.push({distante[vecin], vecin});
                }
            }
        }

        return distante[destinatie] != INT_MAX;
    }

    int fluxMaxim(int sursa, int destinatie) {
        int fluxMaxim = 0;
        std::vector<int> tati(numarNoduri, -1);

        while (dijkstra(sursa, destinatie, tati)) {
            int fluxMinim = INT_MAX;
            int nod = destinatie;

            while (nod != sursa) {
                fluxMinim = std::min(fluxMinim, capacitati[tati[nod]][nod] - flux[tati[nod]][nod]);
                nod = tati[nod];
            }

            fluxMaxim += fluxMinim;
            nod = destinatie;

            while (nod != sursa) {
                flux[tati[nod]][nod] += fluxMinim;
                flux[nod][tati[nod]] -= fluxMinim;
                nod = tati[nod];
            }
        }

        return fluxMaxim;
    }

    int getCostMinim() const {
        int costMinim = 0;

        for (int i = 0; i < numarNoduri; i++) {
            for (int j = 0; j < numarNoduri; j++) {
                costMinim += flux[i][j] * costuri[i][j];
            }
        }

        return costMinim;
    }
};

int main() {
    std::ifstream fin("cc.in");
    std::ofstream fout("cc.out");

    int N;
    fin >> N;

    Graf g(2 * N + 2);

    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            int distance;
            fin >> distance;
            g.adaugaCapacitate(i, j + N, 1, distance);
        }
    }
    fin.close();

    int sursa = 2 * N;
    int destinatie = 2 * N + 1;

    for (int i = 0; i < N; ++i) {
        g.adaugaCapacitate(sursa, i, 1, 0);
    }

    for (int j = 0; j < N; ++j) {
        g.adaugaCapacitate(j + N, destinatie, 1, 0);
    }

    int maxFlow = g.fluxMaxim(sursa, destinatie);
    int minDistanceSum = g.getCostMinim();
    minDistanceSum /= 2;

    fout << minDistanceSum << '\n';
    fout.close();

    return 0;
}