Cod sursa(job #3190429)

Utilizator ChelaruPaulChelaru Paul ChelaruPaul Data 7 ianuarie 2024 16:31:14
Problema Cc Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.3 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>

using namespace std;

ifstream inputFile("cc.in");
ofstream outputFile("cc.out");

int numNodes, sourceNode, targetNode, dist;
vector<vector<int>> adjacencyList, capacity, flow, distanceMatrix;
vector<int> previousNode, minDistance;
int result;

// Funcție pentru parcurgerea în lățime (BFS) pentru găsirea unui drum de la sursă la destinație
int bfs() {
    // Inițializarea nodurilor precedente și a distanței minime pentru fiecare iterație a BFS
    previousNode.assign(targetNode + 1, -1);
    minDistance.assign(targetNode + 1, INT_MAX);
    minDistance[0] = 0;

    queue<pair<int, int>> q;
    q.push({0, INT_MAX});

    while (!q.empty()) {
        int current = q.front().first, minFlowUntilNow = q.front().second;
        q.pop();

        // Parcurgerea vecinilor nodului curent în graf
        for (auto &next : adjacencyList[current]) {
            // Verificarea dacă există o capacitate nefolosită pe muchia de la nodul curent la nodul vecin
            if (minDistance[next] > minDistance[current] + distanceMatrix[current][next] && capacity[current][next] > flow[current][next]) {
                // Actualizarea nodului vecin și adăugarea la coadă pentru explorare ulterioară
                previousNode[next] = current;
                int residualCapacity = capacity[current][next] - flow[current][next];
                int nextMinFlow = residualCapacity > minFlowUntilNow ? minFlowUntilNow : residualCapacity;
                minDistance[next] = minDistance[current] + distanceMatrix[current][next];
                q.push({next, nextMinFlow});
            }
        }
    }

    // Returnează true dacă a fost găsit un drum de la sursă la destinație
    return previousNode[targetNode] >= 0;
}

// Algoritmul Edmonds-Karp pentru găsirea fluxului maxim și a distanței minime
void edmondsKarpAlgorithm() {
    while (true) {
        int flowOfPath = bfs();

        // Dacă nu mai există drumuri augmentate, se oprește
        if (!flowOfPath) break;

        int current = targetNode;
        // Refacerea drumului și actualizarea fluxului pe tot traseul
        while (current != 0) {
            int previous = previousNode[current];
            flow[previous][current] += flowOfPath;
            flow[current][previous] -= flowOfPath;
            current = previous;
        }

        // Adăugarea la distanța totală
        result += minDistance[targetNode];
    }
}

int main() {
    // Citirea numărului de noduri din fișierul de intrare
    inputFile >> numNodes;
    // Calcularea nodului destinație în graf
    targetNode = 2 * numNodes + 1;
    // Inițializarea vectorilor și matricelor pentru graful de flux
    previousNode.resize(targetNode + 1);
    minDistance.resize(targetNode + 1);
    adjacencyList.resize(targetNode + 1, {});
    capacity.assign(targetNode + 1, vector<int>(targetNode + 1, 0));
    flow.resize(targetNode + 1, vector<int>(targetNode + 1, 0));
    distanceMatrix.resize(targetNode + 1, vector<int>(targetNode + 1, 0));

    // Construirea grafului și a matricelor de capacitate și distanță
    for (int i = 1; i <= numNodes; i++) {
        // Adăugarea muchiilor de la sursă către nodurile concurenților
        adjacencyList[0].push_back(i);
        adjacencyList[i].push_back(0);
        capacity[0][i] = 1;

        for (int j = 1; j <= numNodes; j++) {
            // Citirea distanței dintre concurentul i și calculatorul j
            inputFile >> dist;
            // Adăugarea muchiilor între concurenți și calculatoare și inițializarea matricii de distanțe
            adjacencyList[i].push_back(j + numNodes);
            adjacencyList[j + numNodes].push_back(i);
            capacity[i][j + numNodes] = 1;
            distanceMatrix[i][j + numNodes] = dist;
            distanceMatrix[j + numNodes][i] = -dist;
        }
    }

    // Adăugarea muchiilor de la calculatoare la nodul destinație
    for (int i = 1; i <= numNodes; i++) {
        adjacencyList[i + numNodes].push_back(targetNode);
        adjacencyList[targetNode].push_back(i + numNodes);
        capacity[i + numNodes][targetNode] = 1;
    }

    // Apelarea algoritmului Edmonds-Karp
    edmondsKarpAlgorithm();

    // Scrierea rezultatului în fișierul de ieșire
    outputFile << result;

    return 0;
}