Cod sursa(job #3191964)

Utilizator AnacrmCaraiman Ana Anacrm Data 11 ianuarie 2024 04:16:26
Problema Cc Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.51 kb
#include <fstream>
#include <vector>
#include <deque>
#include <bitset>
#include <limits>

using namespace std;

ifstream fin("cc.in");
ofstream fout("cc.out");

const int MAX_N = 210;
const int INF = numeric_limits<int>::max();

int n, sol, cost[MAX_N][MAX_N], capacitate[MAX_N][MAX_N], flux[MAX_N][MAX_N], parinte[MAX_N];
vector<int> graf[MAX_N];
deque<int> coada;
bitset<MAX_N> vizitat;

// Funcție pentru găsirea drumurilor de creștere folosind algoritmul Bellman-Ford
bool bellmanFord() {
    vizitat.reset();
    fill(parinte, parinte + MAX_N, -1);
    vector<int> distanta(MAX_N, INF);

    vizitat[0] = true;
    distanta[0] = 0;
    coada.push_back(0);

    while (!coada.empty()) {
        int nod = coada.front();
        coada.pop_front();
        vizitat[nod] = false;

        for (int vecin : graf[nod]) {
            if (distanta[vecin] > distanta[nod] + cost[nod][vecin] && capacitate[nod][vecin] - flux[nod][vecin] > 0) {
                distanta[vecin] = distanta[nod] + cost[nod][vecin];
                parinte[vecin] = nod;

                if (!vizitat[vecin]) {
                    vizitat[vecin] = true;
                    coada.push_back(vecin);

                    if (vecin == 2 * n + 1)
                        return true; // destinație
                }
            }
        }
    }

    return false; // nu mai există drumuri de creștere
}

int main() {
    fin >> n;

    // construiește graf
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            fin >> cost[i][n + j];
            graf[i].push_back(n + j);
            graf[n + j].push_back(i);
            capacitate[i][n + j] = 1;
        }

        graf[0].push_back(i);
        graf[i].push_back(0);
        capacitate[0][i] = 1;

        graf[n + i].push_back(2 * n + 1);
        graf[2 * n + 1].push_back(n + i);
        capacitate[n + i][2 * n + 1] = 1;
    }

    // algoritm de flux maxim cu cost minim
    while (bellmanFord()) {
        int nod = 2 * n + 1;
        int fluxMinim = INF;

        // flux minim pe drumul de creștere
        while (nod != 0) {
            fluxMinim = min(fluxMinim, capacitate[parinte[nod]][nod] - flux[parinte[nod]][nod]);
            nod = parinte[nod];
        }

        nod = 2 * n + 1;

        // actualizare flux si cost
        while (nod != 0) {
            flux[parinte[nod]][nod] += fluxMinim;
            flux[nod][parinte[nod]] -= fluxMinim;
            sol += fluxMinim * cost[parinte[nod]][nod];
            nod = parinte[nod];
        }
    }

    fout << sol;

    return 0;
}